mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
capability-util: introduce capability_apply() and use it in capability_ambient_set_apply()
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "bitfield.h"
|
||||
#include "capability-list.h"
|
||||
#include "capability-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
@@ -44,6 +45,29 @@ int capability_get(CapabilityQuintet *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int capability_apply(const CapabilityQuintet *q) {
|
||||
assert(q);
|
||||
|
||||
struct __user_cap_header_struct hdr = {
|
||||
.version = _LINUX_CAPABILITY_VERSION_3,
|
||||
.pid = getpid_cached(),
|
||||
};
|
||||
|
||||
struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3] = {
|
||||
{
|
||||
.effective = (uint32_t) (q->effective & UINT32_MAX),
|
||||
.inheritable = (uint32_t) (q->inheritable & UINT32_MAX),
|
||||
.permitted = (uint32_t) (q->permitted & UINT32_MAX),
|
||||
},
|
||||
{
|
||||
.effective = (uint32_t) (q->effective >> 32),
|
||||
.inheritable = (uint32_t) (q->inheritable >> 32),
|
||||
.permitted = (uint32_t) (q->permitted >> 32),
|
||||
},
|
||||
};
|
||||
return RET_NERRNO(syscall(SYS_capset, &hdr, data));
|
||||
}
|
||||
|
||||
unsigned cap_last_cap(void) {
|
||||
static atomic_int saved = INT_MAX;
|
||||
int r, c;
|
||||
@@ -124,25 +148,7 @@ int have_inheritable_cap(unsigned cap) {
|
||||
return BIT_SET(q.inheritable, cap);
|
||||
}
|
||||
|
||||
int capability_update_inherited_set(cap_t caps, uint64_t set) {
|
||||
/* Add capabilities in the set to the inherited caps, drops capabilities not in the set.
|
||||
* Do not apply them yet. */
|
||||
|
||||
for (unsigned i = 0; i <= cap_last_cap(); i++) {
|
||||
cap_flag_value_t flag = set & (UINT64_C(1) << i) ? CAP_SET : CAP_CLEAR;
|
||||
cap_value_t v;
|
||||
|
||||
v = (cap_value_t) i;
|
||||
|
||||
if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, flag) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
|
||||
_cleanup_cap_free_ cap_t caps = NULL;
|
||||
int r;
|
||||
|
||||
/* Remove capabilities requested in ambient set, but not in the bounding set */
|
||||
@@ -160,16 +166,17 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
|
||||
/* Add the capabilities to the ambient set (an possibly also the inheritable set) */
|
||||
|
||||
if (also_inherit) {
|
||||
caps = cap_get_proc();
|
||||
if (!caps)
|
||||
return -errno;
|
||||
CapabilityQuintet q;
|
||||
|
||||
r = capability_update_inherited_set(caps, set);
|
||||
r = capability_get(&q);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
return r;
|
||||
|
||||
if (cap_set_proc(caps) < 0)
|
||||
return -errno;
|
||||
q.inheritable = set;
|
||||
|
||||
r = capability_apply(&q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i <= cap_last_cap(); i++)
|
||||
|
||||
@@ -53,7 +53,6 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now);
|
||||
int capability_bounding_set_drop_usermode(uint64_t keep);
|
||||
|
||||
int capability_ambient_set_apply(uint64_t set, bool also_inherit);
|
||||
int capability_update_inherited_set(cap_t caps, uint64_t ambient_set);
|
||||
|
||||
int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
|
||||
|
||||
|
||||
@@ -183,23 +183,6 @@ static void test_have_effective_cap(void) {
|
||||
assert_se(have_effective_cap(CAP_CHOWN) == 0);
|
||||
}
|
||||
|
||||
static void test_update_inherited_set(void) {
|
||||
cap_t caps;
|
||||
uint64_t set = 0;
|
||||
cap_flag_value_t fv;
|
||||
|
||||
caps = cap_get_proc();
|
||||
assert_se(caps);
|
||||
|
||||
set = (UINT64_C(1) << CAP_CHOWN);
|
||||
|
||||
assert_se(!capability_update_inherited_set(caps, set));
|
||||
assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
|
||||
assert_se(fv == CAP_SET);
|
||||
|
||||
cap_free(caps);
|
||||
}
|
||||
|
||||
static void test_apply_ambient_caps(void) {
|
||||
cap_t caps;
|
||||
uint64_t set = 0;
|
||||
@@ -336,8 +319,6 @@ int main(int argc, char *argv[]) {
|
||||
if (!userns_has_single_user())
|
||||
test_drop_privileges();
|
||||
|
||||
test_update_inherited_set();
|
||||
|
||||
if (!userns_has_single_user())
|
||||
fork_test(test_have_effective_cap);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user