summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-02-22 13:05:44 +0100
committerLennart Poettering <lennart@poettering.net>2023-02-22 23:45:40 +0100
commita649419aae0f24990186eaec5a11bbc169ff8c7d (patch)
tree008f4e19a2de3f1d33e5bc86c7ee98de2b7db657
parentcap-list: add capability_set_to_string_negative() (diff)
downloadsystemd-a649419aae0f24990186eaec5a11bbc169ff8c7d.tar.xz
systemd-a649419aae0f24990186eaec5a11bbc169ff8c7d.zip
capability-util: add new capability_get_ambient() helper
-rw-r--r--src/basic/capability-util.c25
-rw-r--r--src/basic/capability-util.h2
-rw-r--r--src/test/test-capability.c55
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;
}