aboutsummaryrefslogtreecommitdiff
path: root/libcap/cap_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcap/cap_proc.c')
-rw-r--r--libcap/cap_proc.c95
1 files changed, 86 insertions, 9 deletions
diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c
index f70b0e3..3f66d58 100644
--- a/libcap/cap_proc.c
+++ b/libcap/cap_proc.c
@@ -1,13 +1,87 @@
/*
- * Copyright (c) 1997-8,2007,2011 Andrew G Morgan <morgan@kernel.org>
+ * Copyright (c) 1997-8,2007,2011,2019 Andrew G Morgan <morgan@kernel.org>
*
* This file deals with getting and setting capabilities on processes.
*/
+#include <sys/syscall.h>
#include <sys/prctl.h>
+#include <unistd.h>
#include "libcap.h"
+/*
+ * libcap uses this abstraction for all system calls that change
+ * kernel managed capability state. This permits the user to redirect
+ * it for testing and also to better implement posix semantics when
+ * using pthreads.
+ */
+
+static long int _cap_syscall(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3)
+{
+ return syscall(syscall_nr, arg1, arg2, arg3);
+}
+
+static long int _cap_syscall6(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5, long int arg6)
+{
+ return syscall(syscall_nr, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+static long int (*_libcap_syscall)(long int, long int, long int, long int)
+ = _cap_syscall;
+static long int (*_libcap_syscall6)(long int, long int, long int, long int,
+ long int, long int, long int) = _cap_syscall6;
+
+void cap_set_syscall(long int (*new_syscall)(long int,
+ long int, long int, long int),
+ long int (*new_syscall6)(long int,
+ long int, long int, long int,
+ long int, long int, long int))
+{
+ _libcap_syscall = new_syscall;
+ _libcap_syscall6 = new_syscall6;
+}
+
+/*
+ * libcap<->libpsx subtle linking trick. If -lpsx is linked, then this
+ * function will get called when psx is initialized. In so doing,
+ * libcap will opt to use POSIX compliant syscalls for all state
+ * changing system calls - via psx_syscall().
+ */
+void share_psx_syscall(long int (*syscall_fn)(long int,
+ long int, long int, long int),
+ long int (*syscall6_fn)(long int,
+ long int, long int, long int,
+ long int, long int, long int));
+
+void share_psx_syscall(long int (*syscall_fn)(long int,
+ long int, long int, long int),
+ long int (*syscall6_fn)(long int,
+ long int, long int, long int,
+ long int, long int, long int))
+{
+ cap_set_syscall(syscall_fn, syscall6_fn);
+}
+
+static int _libcap_capset(cap_user_header_t header, const cap_user_data_t data)
+{
+ return _libcap_syscall(SYS_capset, (long int) header, (long int) data, 0);
+}
+
+static int _libcap_prctl(long int pr_cmd, long int arg1, long int arg2)
+{
+ return _libcap_syscall(SYS_prctl, pr_cmd, arg1, arg2);
+}
+
+static int _libcap_prctl6(long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5)
+{
+ return _libcap_syscall6(SYS_prctl, pr_cmd, arg1, arg2, arg3, arg4, arg5);
+}
+
cap_t cap_get_proc(void)
{
cap_t result;
@@ -37,7 +111,7 @@ int cap_set_proc(cap_t cap_d)
}
_cap_debug("setting process capabilities");
- retval = capset(&cap_d->head, &cap_d->u[0].set);
+ retval = _libcap_capset(&cap_d->head, &cap_d->u[0].set);
return retval;
}
@@ -85,7 +159,10 @@ cap_t cap_get_pid(pid_t pid)
return result;
}
-/* set the caps on a specific process/pg etc.. */
+/*
+ * set the caps on a specific process/pg etc.. The kernel has long
+ * since deprecated this asynchronus interface.
+ */
int capsetp(pid_t pid, cap_t cap_d)
{
@@ -114,7 +191,7 @@ int cap_get_bound(cap_value_t cap)
{
int result;
- result = prctl(PR_CAPBSET_READ, pr_arg(cap));
+ result = _libcap_prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
@@ -128,7 +205,7 @@ int cap_drop_bound(cap_value_t cap)
{
int result;
- result = prctl(PR_CAPBSET_DROP, pr_arg(cap));
+ result = _libcap_prctl(PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
@@ -166,8 +243,8 @@ int cap_set_ambient(cap_value_t cap, cap_flag_value_t set)
errno = EINVAL;
return -1;
}
- result = prctl(PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
- pr_arg(0), pr_arg(0));
+ result = _libcap_prctl6(PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
+ pr_arg(0), pr_arg(0), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
@@ -181,8 +258,8 @@ int cap_reset_ambient()
{
int result;
- result = prctl(PR_CAP_AMBIENT, pr_arg(PR_CAP_AMBIENT_CLEAR_ALL),
- pr_arg(0), pr_arg(0), pr_arg(0));
+ result = _libcap_prctl6(PR_CAP_AMBIENT, pr_arg(PR_CAP_AMBIENT_CLEAR_ALL),
+ pr_arg(0), pr_arg(0), pr_arg(0), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;