From: Yu Watanabe Date: Thu, 23 Oct 2025 14:16:06 +0000 (+0900) Subject: capability-util: introduce capability_apply() and use it in capability_ambient_set_ap... X-Git-Tag: v259-rc1~255^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa8ab67a6dbdfd42490ad49821435f85d22909e0;p=thirdparty%2Fsystemd.git capability-util: introduce capability_apply() and use it in capability_ambient_set_apply() --- diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index ee665df6f9b..801292ac798 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -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++) diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h index 78bd75db7b6..e911c7bae20 100644 --- a/src/basic/capability-util.h +++ b/src/basic/capability-util.h @@ -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); diff --git a/src/test/test-capability-util.c b/src/test/test-capability-util.c index 67a61c7eaf0..ef04e77a5c9 100644 --- a/src/test/test-capability-util.c +++ b/src/test/test-capability-util.c @@ -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);