]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/test/test-capability.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / test / test-capability.c
index 730dbf8cbdaaca84d5c748991c30ce3f45efa232..0ff56070b163fb25b4f1188641f826f135bbc25f 100644 (file)
@@ -1,27 +1,35 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <netinet/in.h>
 #include <pwd.h>
-#include <sys/capability.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
+#define TEST_CAPABILITY_C
+
 #include "alloc-util.h"
 #include "capability-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "macro.h"
+#include "missing_prctl.h"
 #include "parse-util.h"
+#include "string-util.h"
 #include "tests.h"
-#include "util.h"
 
 static uid_t test_uid = -1;
 static gid_t test_gid = -1;
 
+#if HAS_FEATURE_ADDRESS_SANITIZER
+/* Keep CAP_SYS_PTRACE when running under Address Sanitizer */
+static const uint64_t test_flags = UINT64_C(1) << CAP_SYS_PTRACE;
+#else
 /* We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage */
-static uint64_t test_flags = 1ULL << CAP_DAC_OVERRIDE;
+static const uint64_t test_flags = UINT64_C(1) << CAP_DAC_OVERRIDE;
+#endif
 
 /* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */
 static void test_last_cap_file(void) {
@@ -30,6 +38,8 @@ static void test_last_cap_file(void) {
         int r;
 
         r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
+        if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* kernel pre 3.2 or no access */
+                return;
         assert_se(r >= 0);
 
         r = safe_atolu(content, &val);
@@ -93,7 +103,7 @@ static int setup_tests(bool *run_ambient) {
 
         nobody = getpwnam(NOBODY_USER_NAME);
         if (!nobody)
-                return log_error_errno(errno, "Could not find nobody user: %m");
+                return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Could not find nobody user: %m");
 
         test_uid = nobody->pw_uid;
         test_gid = nobody->pw_gid;
@@ -180,8 +190,6 @@ static void test_update_inherited_set(void) {
 
         caps = cap_get_proc();
         assert_se(caps);
-        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
-        assert(fv == CAP_CLEAR);
 
         set = (UINT64_C(1) << CAP_CHOWN);
 
@@ -192,17 +200,11 @@ static void test_update_inherited_set(void) {
         cap_free(caps);
 }
 
-static void test_set_ambient_caps(void) {
+static void test_apply_ambient_caps(void) {
         cap_t caps;
         uint64_t set = 0;
         cap_flag_value_t fv;
 
-        caps = cap_get_proc();
-        assert_se(caps);
-        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
-        assert(fv == CAP_CLEAR);
-        cap_free(caps);
-
         assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0);
 
         set = (UINT64_C(1) << CAP_CHOWN);
@@ -210,11 +212,40 @@ static void test_set_ambient_caps(void) {
         assert_se(!capability_ambient_set_apply(set, true));
 
         caps = cap_get_proc();
+        assert_se(caps);
         assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
-        assert(fv == CAP_SET);
+        assert_se(fv == CAP_SET);
         cap_free(caps);
 
         assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 1);
+
+        assert_se(!capability_ambient_set_apply(0, true));
+        caps = cap_get_proc();
+        assert_se(caps);
+        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+        assert_se(fv == CAP_CLEAR);
+        cap_free(caps);
+
+        assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0);
+}
+
+static void test_ensure_cap_64bit(void) {
+        _cleanup_free_ char *content = NULL;
+        unsigned long p = 0;
+        int r;
+
+        r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
+        if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* kernel pre 3.2 or no access */
+                return;
+        assert_se(r >= 0);
+
+        assert_se(safe_atolu(content, &p) >= 0);
+
+        /* If caps don't fit into 64bit anymore, we have a problem, fail the test. */
+        assert_se(p <= 63);
+
+        /* Also check for the header definition */
+        assert_cc(CAP_LAST_CAP <= 63);
 }
 
 int main(int argc, char *argv[]) {
@@ -222,6 +253,8 @@ int main(int argc, char *argv[]) {
 
         test_setup_logging(LOG_INFO);
 
+        test_ensure_cap_64bit();
+
         test_last_cap_file();
         test_last_cap_probe();
 
@@ -241,7 +274,7 @@ int main(int argc, char *argv[]) {
         fork_test(test_have_effective_cap);
 
         if (run_ambient)
-                fork_test(test_set_ambient_caps);
+                fork_test(test_apply_ambient_caps);
 
         return 0;
 }