1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-06 13:17:44 +03:00

tree-wide: have_effective_cap() may return negative errno

This commit is contained in:
Yu Watanabe 2022-12-23 17:29:40 +09:00
parent d7301331e8
commit 26c45a6c1d
7 changed files with 30 additions and 17 deletions

View 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;

View 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;

View 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. */

View 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++) {

View 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);

View 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) {

View 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. */