]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
capability-util: introduce capability_apply() and use it in capability_ambient_set_ap...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 23 Oct 2025 14:16:06 +0000 (23:16 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 23 Oct 2025 16:52:59 +0000 (01:52 +0900)
src/basic/capability-util.c
src/basic/capability-util.h
src/test/test-capability-util.c

index ee665df6f9bfa3b5bab0a1d170fdfb6c9249e634..801292ac7983cff7140cae3c3a3ebc2038c945d0 100644 (file)
@@ -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++)
index 78bd75db7b62abbd5102511f07161aa6a9c47bd8..e911c7bae20f0d353c968a1defd2afbfe1125a5f 100644 (file)
@@ -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);
 
index 67a61c7eaf020024a164c423729602818fdcb6a1..ef04e77a5c95b202e607bdc55400a0f63711b779 100644 (file)
@@ -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);