mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
capability-util: introduce capability_get() and use it in have_effective_cap()
capability_get() is a wrapper of capget() syscall and converts its result to CapabilityQuintet. This also introduce have_inheritable_cap(), which is similar to have_effective_cap(). It is currently unused, but will be used later.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
@@ -20,6 +21,29 @@
|
||||
#include "stat-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
int capability_get(CapabilityQuintet *ret) {
|
||||
assert(ret);
|
||||
|
||||
struct __user_cap_header_struct hdr = {
|
||||
.version = _LINUX_CAPABILITY_VERSION_3,
|
||||
.pid = getpid_cached(),
|
||||
};
|
||||
|
||||
assert_cc(_LINUX_CAPABILITY_U32S_3 == 2);
|
||||
struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3];
|
||||
if (syscall(SYS_capget, &hdr, data) < 0)
|
||||
return -errno;
|
||||
|
||||
*ret = (CapabilityQuintet) {
|
||||
.effective = (uint64_t) data[0].effective | ((uint64_t) data[1].effective << 32),
|
||||
.bounding = UINT64_MAX,
|
||||
.inheritable = (uint64_t) data[0].inheritable | ((uint64_t) data[1].inheritable << 32),
|
||||
.permitted = (uint64_t) data[0].permitted | ((uint64_t) data[1].permitted << 32),
|
||||
.ambient = UINT64_MAX,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned cap_last_cap(void) {
|
||||
static atomic_int saved = INT_MAX;
|
||||
int r, c;
|
||||
@@ -74,19 +98,30 @@ unsigned cap_last_cap(void) {
|
||||
return c;
|
||||
}
|
||||
|
||||
int have_effective_cap(int value) {
|
||||
_cleanup_cap_free_ cap_t cap = NULL;
|
||||
cap_flag_value_t fv = CAP_CLEAR; /* To avoid false-positive use-of-uninitialized-value error reported
|
||||
* by fuzzers. */
|
||||
int have_effective_cap(unsigned cap) {
|
||||
CapabilityQuintet q;
|
||||
int r;
|
||||
|
||||
cap = cap_get_proc();
|
||||
if (!cap)
|
||||
return -errno;
|
||||
assert(cap <= CAP_LIMIT);
|
||||
|
||||
if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
|
||||
return -errno;
|
||||
r = capability_get(&q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return fv == CAP_SET;
|
||||
return BIT_SET(q.effective, cap);
|
||||
}
|
||||
|
||||
int have_inheritable_cap(unsigned cap) {
|
||||
CapabilityQuintet q;
|
||||
int r;
|
||||
|
||||
assert(cap <= CAP_LIMIT);
|
||||
|
||||
r = capability_get(&q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return BIT_SET(q.inheritable, cap);
|
||||
}
|
||||
|
||||
int capability_update_inherited_set(cap_t caps, uint64_t set) {
|
||||
|
||||
@@ -43,8 +43,11 @@ static inline bool capability_is_set(uint64_t v) {
|
||||
return v != CAP_MASK_UNSET;
|
||||
}
|
||||
|
||||
int capability_get(CapabilityQuintet *ret);
|
||||
|
||||
unsigned cap_last_cap(void);
|
||||
int have_effective_cap(int value);
|
||||
int have_effective_cap(unsigned cap);
|
||||
int have_inheritable_cap(unsigned cap);
|
||||
int capability_gain_cap_setpcap(cap_t *ret_before_caps);
|
||||
int capability_bounding_set_drop(uint64_t keep, bool right_now);
|
||||
int capability_bounding_set_drop_usermode(uint64_t keep);
|
||||
|
||||
Reference in New Issue
Block a user