]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
capability-util: add new capability_get_ambient() helper 26557/head
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Feb 2023 12:05:44 +0000 (13:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 22 Feb 2023 22:45:40 +0000 (23:45 +0100)
src/basic/capability-util.c
src/basic/capability-util.h
src/test/test-capability.c

index bda7cbf45c5a30255f95719b0f477681cd016c52..87fb2203f0896650de9b106ee2004c643e71705c 100644 (file)
@@ -605,3 +605,28 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
 
         return 0;
 }
+
+int capability_get_ambient(uint64_t *ret) {
+        uint64_t a = 0;
+        int r;
+
+        assert(ret);
+
+        if (!ambient_capabilities_supported()) {
+                *ret = 0;
+                return 0;
+        }
+
+        for (unsigned i = 0; i <= cap_last_cap(); i++) {
+                r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
+                if (r < 0)
+                        return -errno;
+
+                if (r)
+                        a |= UINT64_C(1) << i;
+        }
+
+
+        *ret = a;
+        return 1;
+}
index 07b13862c7941af01d0e2c3a2d57b72eaa291d87..3e0f901a3d3145ac620c8f4e209f9480746d5948 100644 (file)
@@ -83,3 +83,5 @@ static inline bool capability_quintet_is_set(const CapabilityQuintet *q) {
 bool capability_quintet_mangle(CapabilityQuintet *q);
 
 int capability_quintet_enforce(const CapabilityQuintet *q);
+
+int capability_get_ambient(uint64_t *ret);
index dbb258c7d261bb50f10ee200e84fbc7d4ef4bc49..e989065f4928c3f00a240a6a77a6b55e442edb32 100644 (file)
@@ -17,6 +17,7 @@
 #include "macro.h"
 #include "missing_prctl.h"
 #include "parse-util.h"
+#include "process-util.h"
 #include "string-util.h"
 #include "tests.h"
 
@@ -247,10 +248,60 @@ static void test_ensure_cap_64bit(void) {
         assert_cc(CAP_LAST_CAP <= 63);
 }
 
+static void test_capability_get_ambient(void) {
+        uint64_t c;
+        int r;
+
+        assert_se(capability_get_ambient(&c) >= 0);
+
+        r = safe_fork("(getambient)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
+        assert_se(r >= 0);
+
+        if (r == 0) {
+                int x, y;
+                /* child */
+                assert_se(capability_get_ambient(&c) >= 0);
+
+                x = capability_ambient_set_apply(
+                                (UINT64_C(1) << CAP_MKNOD)|
+                                (UINT64_C(1) << CAP_LINUX_IMMUTABLE),
+                                /* also_inherit= */ true);
+                assert_se(x >= 0 || ERRNO_IS_PRIVILEGE(x));
+
+                assert_se(capability_get_ambient(&c) >= 0);
+                assert_se(x < 0 || FLAGS_SET(c, UINT64_C(1) << CAP_MKNOD));
+                assert_se(x < 0 || FLAGS_SET(c, UINT64_C(1) << CAP_LINUX_IMMUTABLE));
+                assert_se(x < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_SETPCAP));
+
+                y = capability_bounding_set_drop(
+                                ((UINT64_C(1) << CAP_LINUX_IMMUTABLE)|
+                                 (UINT64_C(1) << CAP_SETPCAP)),
+                                /* right_now= */ true);
+                assert_se(y >= 0 || ERRNO_IS_PRIVILEGE(y));
+
+                assert_se(capability_get_ambient(&c) >= 0);
+                assert_se(x < 0 || y < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_MKNOD));
+                assert_se(x < 0 || y < 0 || FLAGS_SET(c, UINT64_C(1) << CAP_LINUX_IMMUTABLE));
+                assert_se(x < 0 || y < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_SETPCAP));
+
+                y = capability_bounding_set_drop(
+                                (UINT64_C(1) << CAP_SETPCAP),
+                                /* right_now= */ true);
+                assert_se(y >= 0 || ERRNO_IS_PRIVILEGE(y));
+
+                assert_se(capability_get_ambient(&c) >= 0);
+                assert_se(x < 0 || y < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_MKNOD));
+                assert_se(x < 0 || y < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_LINUX_IMMUTABLE));
+                assert_se(x < 0 || y < 0 || !FLAGS_SET(c, UINT64_C(1) << CAP_SETPCAP));
+
+                _exit(EXIT_SUCCESS);
+        }
+}
+
 int main(int argc, char *argv[]) {
         bool run_ambient;
 
-        test_setup_logging(LOG_INFO);
+        test_setup_logging(LOG_DEBUG);
 
         test_ensure_cap_64bit();
 
@@ -275,5 +326,7 @@ int main(int argc, char *argv[]) {
         if (run_ambient)
                 fork_test(test_apply_ambient_caps);
 
+        test_capability_get_ambient();
+
         return 0;
 }