]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: have_effective_cap() may return negative errno
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 23 Dec 2022 08:29:40 +0000 (17:29 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 23 Dec 2022 13:11:00 +0000 (22:11 +0900)
src/basic/argv-util.c
src/core/audit-fd.c
src/core/execute.c
src/core/kmod-setup.c
src/sysext/sysext.c
src/test/test-capability.c
src/tmpfiles/tmpfiles.c

index fe152502fd8383ca86d6b15500b6684520113307..b8c371ede5b255f5f59f8f646eff87790a4ecff0 100644 (file)
@@ -79,6 +79,7 @@ bool argv_looks_like_help(int argc, char **argv) {
 
 static int update_argv(const char name[], size_t l) {
         static int can_do = -1;
+        int r;
 
         if (can_do == 0)
                 return 0;
@@ -86,13 +87,15 @@ static int update_argv(const char name[], size_t l) {
 
         /* Calling prctl() with PR_SET_MM_ARG_{START,END} requires CAP_SYS_RESOURCE so let's use this as quick bypass
          * check, to avoid calling mmap() should PR_SET_MM_ARG_{START,END} fail with EPERM later on anyway. */
-        if (!have_effective_cap(CAP_SYS_RESOURCE))
+        r = have_effective_cap(CAP_SYS_RESOURCE);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to check if we have enough privileges: %m");
+        if (r == 0)
                 return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
                                        "Skipping PR_SET_MM, as we don't have privileges.");
 
         static size_t mm_size = 0;
         static char *mm = NULL;
-        int r;
 
         if (mm_size < l+1) {
                 size_t nn_size;
index 872280f7981614dc87e5846ab981df29785fc7cb..6674fa8379e612909a9c6c55936c81e433891caa 100644 (file)
@@ -19,7 +19,7 @@ static int audit_fd;
 int get_audit_fd(void) {
 
         if (!initialized) {
-                if (have_effective_cap(CAP_AUDIT_WRITE) == 0) {
+                if (have_effective_cap(CAP_AUDIT_WRITE) <= 0) {
                         audit_fd = -EPERM;
                         initialized = true;
 
index 5dc8535a47a99ea956d396d665f7937d7adb995a..9f0c5a85bf45716a04a7c4e05ed515af27b9040f 100644 (file)
@@ -1433,7 +1433,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
         if (c->no_new_privileges)
                 return true;
 
-        if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */
+        if (have_effective_cap(CAP_SYS_ADMIN) > 0) /* if we are privileged, we don't need NNP */
                 return false;
 
         /* We need NNP if we have any form of seccomp and are unprivileged */
@@ -2117,7 +2117,7 @@ static int setup_private_users(uid_t ouid, gid_t ogid, uid_t uid, gid_t gid) {
          * does not need CAP_SETUID to write the single line mapping to itself. */
 
         /* Can only set up multiple mappings with CAP_SETUID. */
-        if (have_effective_cap(CAP_SETUID) && uid != ouid && uid_is_valid(uid))
+        if (have_effective_cap(CAP_SETUID) > 0 && uid != ouid && uid_is_valid(uid))
                 r = asprintf(&uid_map,
                              UID_FMT " " UID_FMT " 1\n"     /* Map $OUID → $OUID */
                              UID_FMT " " UID_FMT " 1\n",    /* Map $UID → $UID */
@@ -2131,7 +2131,7 @@ static int setup_private_users(uid_t ouid, gid_t ogid, uid_t uid, gid_t gid) {
                 return -ENOMEM;
 
         /* Can only set up multiple mappings with CAP_SETGID. */
-        if (have_effective_cap(CAP_SETGID) && gid != ogid && gid_is_valid(gid))
+        if (have_effective_cap(CAP_SETGID) > 0 && gid != ogid && gid_is_valid(gid))
                 r = asprintf(&gid_map,
                              GID_FMT " " GID_FMT " 1\n"     /* Map $OGID → $OGID */
                              GID_FMT " " GID_FMT " 1\n",    /* Map $GID → $GID */
@@ -4669,7 +4669,7 @@ static int exec_child(
                 }
         }
 
-        if (needs_sandboxing && context->private_users && !have_effective_cap(CAP_SYS_ADMIN)) {
+        if (needs_sandboxing && context->private_users && have_effective_cap(CAP_SYS_ADMIN) <= 0) {
                 /* If we're unprivileged, set up the user namespace first to enable use of the other namespaces.
                  * Users with CAP_SYS_ADMIN can set up user namespaces last because they will be able to
                  * set up the all of the other namespaces (i.e. network, mount, UTS) without a user namespace. */
index dcbc28205fef1317ae40992c57a921e6a1bf857c..e84374377788227fecafabab20e26e3211112be9 100644 (file)
@@ -130,7 +130,7 @@ int kmod_setup(void) {
         _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL;
         unsigned i;
 
-        if (have_effective_cap(CAP_SYS_MODULE) == 0)
+        if (have_effective_cap(CAP_SYS_MODULE) <= 0)
                 return 0;
 
         for (i = 0; i < ELEMENTSOF(kmod_table); i++) {
index b9147fbd78d67b961cde87045656436702d75160..4fbc5e877e813d0470447e73e6d8f839c18a61cb 100644 (file)
@@ -153,8 +153,12 @@ static int unmerge(void) {
 }
 
 static int verb_unmerge(int argc, char **argv, void *userdata) {
+        int r;
 
-        if (!have_effective_cap(CAP_SYS_ADMIN))
+        r = have_effective_cap(CAP_SYS_ADMIN);
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if we have enough privileges: %m");
+        if (r == 0)
                 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
 
         return unmerge();
@@ -761,7 +765,10 @@ static int verb_merge(int argc, char **argv, void *userdata) {
         _cleanup_(hashmap_freep) Hashmap *images = NULL;
         int r;
 
-        if (!have_effective_cap(CAP_SYS_ADMIN))
+        r = have_effective_cap(CAP_SYS_ADMIN);
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if we have enough privileges: %m");
+        if (r == 0)
                 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
 
         r = image_discover_and_read_metadata(&images);
@@ -796,7 +803,10 @@ static int verb_refresh(int argc, char **argv, void *userdata) {
         _cleanup_(hashmap_freep) Hashmap *images = NULL;
         int r;
 
-        if (!have_effective_cap(CAP_SYS_ADMIN))
+        r = have_effective_cap(CAP_SYS_ADMIN);
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if we have enough privileges: %m");
+        if (r == 0)
                 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
 
         r = image_discover_and_read_metadata(&images);
index c5596bb6c3c2765324630ee4db8bf6a4dbebc6d3..dbb258c7d261bb50f10ee200e84fbc7d4ef4bc49 100644 (file)
@@ -161,7 +161,7 @@ static void test_drop_privileges_fail(void) {
 static void test_drop_privileges(void) {
         fork_test(test_drop_privileges_fail);
 
-        if (have_effective_cap(CAP_NET_RAW) == 0) /* The remaining two tests only work if we have CAP_NET_RAW
+        if (have_effective_cap(CAP_NET_RAW) <= 0) /* The remaining two tests only work if we have CAP_NET_RAW
                                                    * in the first place. If we are run in some restricted
                                                    * container environment we might not. */
                 return;
@@ -171,15 +171,15 @@ static void test_drop_privileges(void) {
 }
 
 static void test_have_effective_cap(void) {
-        assert_se(have_effective_cap(CAP_KILL));
-        assert_se(have_effective_cap(CAP_CHOWN));
+        assert_se(have_effective_cap(CAP_KILL) > 0);
+        assert_se(have_effective_cap(CAP_CHOWN) > 0);
 
         assert_se(drop_privileges(test_uid, test_gid, test_flags | (1ULL << CAP_KILL)) >= 0);
         assert_se(getuid() == test_uid);
         assert_se(getgid() == test_gid);
 
-        assert_se(have_effective_cap(CAP_KILL));
-        assert_se(!have_effective_cap(CAP_CHOWN));
+        assert_se(have_effective_cap(CAP_KILL) > 0);
+        assert_se(have_effective_cap(CAP_CHOWN) == 0);
 }
 
 static void test_update_inherited_set(void) {
index 538d5273cff96230e83727961d9a3f2308ce74a4..5fb4cbf04aa9ac4934900e22144a6186df788f40 100644 (file)
@@ -2520,7 +2520,7 @@ static int create_item(Item *i) {
 
         case CREATE_BLOCK_DEVICE:
         case CREATE_CHAR_DEVICE:
-                if (have_effective_cap(CAP_MKNOD) == 0) {
+                if (have_effective_cap(CAP_MKNOD) <= 0) {
                         /* In a container we lack CAP_MKNOD. We shouldn't attempt to create the device node in that
                          * case to avoid noise, and we don't support virtualized devices in containers anyway. */