From: dongshengyuan <545258830@qq.com> Date: Mon, 13 Jul 2026 06:12:30 +0000 (+0800) Subject: run: reset groups before scope uid switch X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=df3a08b244eaed95a7869b590e43180ce1572c85;p=thirdparty%2Fsystemd.git run: reset groups before scope uid switch Reproducer: sudo systemd-run --scope --uid=nobody /usr/bin/id Before, the command ran as nobody but kept the caller supplementary root group, for example groups=65534(nogroup),0(root). Scope mode performs the uid/gid switch locally, so initialize the target user groups before dropping privileges. Follow-up for 4de33e7f3238a6fe616e61139ab87e221572e5e5 --- diff --git a/src/run/run.c b/src/run/run.c index 2fffa66301e..5d95ee8a22a 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -2517,6 +2517,17 @@ static int start_transient_service(sd_bus *bus) { return EXIT_SUCCESS; } +static int log_scope_group_setup_errno(int r, gid_t gid, const char *message) { + assert(r < 0); + assert(message); + + if (!ERRNO_IS_PRIVILEGE(r) || gid != getgid()) + return log_error_errno(r, "%s: %m", message); + + log_debug_errno(r, "%s, ignoring: %m", message); + return 0; +} + static int start_transient_scope(sd_bus *bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; @@ -2623,26 +2634,22 @@ static int start_transient_scope(sd_bus *bus) { return log_error_errno(errno, "Failed to set nice level: %m"); } + gid_t gid = GID_INVALID; if (arg_exec_group) { - gid_t gid; - r = get_group_creds(arg_exec_group, /* flags= */ 0, /* ret_name= */ NULL, &gid); if (r < 0) return log_error_errno(r, "Failed to resolve group '%s': %s", arg_exec_group, STRERROR_GROUP(r)); - - if (setresgid(gid, gid, gid) < 0) - return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); } + uid_t uid = UID_INVALID; if (arg_exec_user) { _cleanup_free_ char *user = NULL, *home = NULL, *shell = NULL; - uid_t uid; - gid_t gid; + gid_t user_gid; r = get_user_creds(arg_exec_user, USER_CREDS_CLEAN|USER_CREDS_SUPPRESS_PLACEHOLDER|USER_CREDS_PREFER_NSS, - &user, &uid, &gid, &home, &shell); + &user, &uid, &user_gid, &home, &shell); if (r < 0) return log_error_errno(r, "Failed to resolve user '%s': %s", arg_exec_user, STRERROR_USER(r)); @@ -2669,14 +2676,33 @@ static int start_transient_scope(sd_bus *bus) { if (r < 0) return log_oom(); - if (!arg_exec_group && - setresgid(gid, gid, gid) < 0) - return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); + if (!gid_is_valid(gid)) + gid = user_gid; - if (setresuid(uid, uid, uid) < 0) - return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid); + r = initgroups_wrapper(arg_exec_user, gid); + if (r < 0) { + r = log_scope_group_setup_errno( + r, + gid, + strjoina("Failed to initialize supplementary groups for user '", arg_exec_user, "'")); + if (r < 0) + return r; + } + } else if (gid_is_valid(gid)) { + r = maybe_setgroups(/* size= */ 0, /* list= */ NULL); + if (r < 0) { + r = log_scope_group_setup_errno(r, gid, "Failed to drop supplementary groups"); + if (r < 0) + return r; + } } + if (gid_is_valid(gid) && setresgid(gid, gid, gid) < 0) + return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); + + if (uid_is_valid(uid) && setresuid(uid, uid, uid) < 0) + return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid); + if (arg_working_directory && chdir(arg_working_directory) < 0) return log_error_errno(errno, "Failed to change directory to '%s': %m", arg_working_directory); diff --git a/test/units/TEST-74-AUX-UTILS.run.sh b/test/units/TEST-74-AUX-UTILS.run.sh index 5a67ef3f10a..acd7bc5b6c9 100755 --- a/test/units/TEST-74-AUX-UTILS.run.sh +++ b/test/units/TEST-74-AUX-UTILS.run.sh @@ -111,6 +111,10 @@ systemd-run --scope --slice-inherit --slice=foo \ bash -xec '[[ "$(