diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-02-22 13:05:44 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2023-02-22 23:45:40 +0100 |
commit | a649419aae0f24990186eaec5a11bbc169ff8c7d (patch) | |
tree | 008f4e19a2de3f1d33e5bc86c7ee98de2b7db657 | |
parent | cap-list: add capability_set_to_string_negative() (diff) | |
download | systemd-a649419aae0f24990186eaec5a11bbc169ff8c7d.tar.xz systemd-a649419aae0f24990186eaec5a11bbc169ff8c7d.zip |
capability-util: add new capability_get_ambient() helper
-rw-r--r-- | src/basic/capability-util.c | 25 | ||||
-rw-r--r-- | src/basic/capability-util.h | 2 | ||||
-rw-r--r-- | src/test/test-capability.c | 55 |
3 files changed, 81 insertions, 1 deletions
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index bda7cbf45c..87fb2203f0 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -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; +} diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h index 07b13862c7..3e0f901a3d 100644 --- a/src/basic/capability-util.h +++ b/src/basic/capability-util.h @@ -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); diff --git a/src/test/test-capability.c b/src/test/test-capability.c index dbb258c7d2..e989065f49 100644 --- a/src/test/test-capability.c +++ b/src/test/test-capability.c @@ -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; } |