From: Yu Watanabe Date: Fri, 23 Dec 2022 08:29:40 +0000 (+0900) Subject: tree-wide: have_effective_cap() may return negative errno X-Git-Tag: v253-rc1~221 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=26c45a6c1d340e344157f7a6340782b4934b579f;p=thirdparty%2Fsystemd.git tree-wide: have_effective_cap() may return negative errno --- diff --git a/src/basic/argv-util.c b/src/basic/argv-util.c index fe152502fd8..b8c371ede5b 100644 --- a/src/basic/argv-util.c +++ b/src/basic/argv-util.c @@ -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; diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c index 872280f7981..6674fa8379e 100644 --- a/src/core/audit-fd.c +++ b/src/core/audit-fd.c @@ -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; diff --git a/src/core/execute.c b/src/core/execute.c index 5dc8535a47a..9f0c5a85bf4 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -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. */ diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index dcbc28205fe..e8437437778 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -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++) { diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index b9147fbd78d..4fbc5e877e8 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -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); diff --git a/src/test/test-capability.c b/src/test/test-capability.c index c5596bb6c3c..dbb258c7d26 100644 --- a/src/test/test-capability.c +++ b/src/test/test-capability.c @@ -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) { diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 538d5273cff..5fb4cbf04aa 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -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. */