]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-util: add new helper fully_set_uid_gid()
authorLennart Poettering <lennart@poettering.net>
Wed, 29 Nov 2023 16:45:06 +0000 (17:45 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 6 Dec 2023 21:11:38 +0000 (22:11 +0100)
Usually when we do setresuid() we also do setesgid() and setgroups().
Let's add a common helper that does all three, and use it everywhere.

src/basic/user-util.c
src/basic/user-util.h
src/core/exec-invoke.c
src/home/homed-home.c
src/home/homework-fscrypt.c
src/nspawn/nspawn-setuid.c
src/test/test-socket-util.c

index 9ae8577238290588b2b66da27a0c538854406082..8aaffe8d0448d715977232f5fa72ee3c78a769f4 100644 (file)
@@ -661,17 +661,26 @@ int get_shell(char **ret) {
         return path_simplify_alloc(e, ret);
 }
 
-int reset_uid_gid(void) {
+int fully_set_uid_gid(uid_t uid, gid_t gid, const gid_t supplementary_gids[], size_t n_supplementary_gids) {
         int r;
 
-        r = maybe_setgroups(0, NULL);
+        assert(supplementary_gids || n_supplementary_gids == 0);
+
+        /* Sets all UIDs and all GIDs to the specified ones. Drops all auxiliary GIDs */
+
+        r = maybe_setgroups(n_supplementary_gids, supplementary_gids);
         if (r < 0)
                 return r;
 
-        if (setresgid(0, 0, 0) < 0)
-                return -errno;
+        if (gid_is_valid(gid))
+                if (setresgid(gid, gid, gid) < 0)
+                        return -errno;
+
+        if (uid_is_valid(uid))
+                if (setresuid(uid, uid, uid) < 0)
+                        return -errno;
 
-        return RET_NERRNO(setresuid(0, 0, 0));
+        return 0;
 }
 
 int take_etc_passwd_lock(const char *root) {
index f394f6251d7a0732fbefc87231e1a28e69db7834..b3e254662eba843f73c3e809f472865731e6e6aa 100644 (file)
@@ -57,7 +57,10 @@ int getgroups_alloc(gid_t** gids);
 int get_home_dir(char **ret);
 int get_shell(char **ret);
 
-int reset_uid_gid(void);
+int fully_set_uid_gid(uid_t uid, gid_t gid, const gid_t supplementary_gids[], size_t n_supplementary_gids);
+static inline int reset_uid_gid(void) {
+        return fully_set_uid_gid(0, 0, NULL, 0);
+}
 
 int take_etc_passwd_lock(const char *root);
 
index 74c910fc1239dedc9994caa2beef94194e7232d6..e44eacd8ed1483557f77a0500561ec5a30bd5773 100644 (file)
@@ -1220,13 +1220,9 @@ static int setup_pam(
                  * PR_SET_PDEATHSIG work in most cases.  If this fails, ignore the error - but expect sd-pam
                  * threads to fail to exit normally */
 
-                r = maybe_setgroups(0, NULL);
+                r = fully_set_uid_gid(uid, gid, /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
                 if (r < 0)
-                        log_warning_errno(r, "Failed to setgroups() in sd-pam: %m");
-                if (setresgid(gid, gid, gid) < 0)
-                        log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m");
-                if (setresuid(uid, uid, uid) < 0)
-                        log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m");
+                        log_warning_errno(r, "Failed to drop privileges in sd-pam: %m");
 
                 (void) ignore_signals(SIGPIPE);
 
index 37b3270841e0c246053a46e5ae53c2629bc09b12..7673e5043576bc830e9d0272f10a04cbfc0b3a16 100644 (file)
@@ -2085,23 +2085,11 @@ int home_killall(Home *h) {
         if (r < 0)
                 return r;
         if (r == 0) {
-                gid_t gid;
-
                 /* Child */
 
-                gid = user_record_gid(h->record);
-                if (setresgid(gid, gid, gid) < 0) {
-                        log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
-                        _exit(EXIT_FAILURE);
-                }
-
-                if (setgroups(0, NULL) < 0) {
-                        log_error_errno(errno, "Failed to reset auxiliary groups list: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
-                if (setresuid(h->uid, h->uid, h->uid) < 0) {
-                        log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", h->uid);
+                r = fully_set_uid_gid(h->uid, user_record_gid(h->record), /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m", h->uid, user_record_gid(h->record));
                         _exit(EXIT_FAILURE);
                 }
 
index 6aae1d26268576e0ad3a471b9723ac21fb609576..ad0b69b021cbd4d087a3bcdf451d73a9242512f5 100644 (file)
@@ -319,23 +319,11 @@ int home_setup_fscrypt(
                 if (r < 0)
                         return log_error_errno(r, "Failed install encryption key in user's keyring: %m");
                 if (r == 0) {
-                        gid_t gid;
-
                         /* Child */
 
-                        gid = user_record_gid(h);
-                        if (setresgid(gid, gid, gid) < 0) {
-                                log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
-                                _exit(EXIT_FAILURE);
-                        }
-
-                        if (setgroups(0, NULL) < 0) {
-                                log_error_errno(errno, "Failed to reset auxiliary groups list: %m");
-                                _exit(EXIT_FAILURE);
-                        }
-
-                        if (setresuid(h->uid, h->uid, h->uid) < 0) {
-                                log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", h->uid);
+                        r = fully_set_uid_gid(h->uid, user_record_gid(h), /* supplementary_gids= */ NULL, /* n_supplementary_gids= */ 0);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m", h->uid, user_record_gid(h));
                                 _exit(EXIT_FAILURE);
                         }
 
index 2d67c3d9de818acc723f11b9887737c14176ace6..e350b228064d87cd9095f7dd65f5e912b2dfe718 100644 (file)
@@ -56,6 +56,8 @@ int change_uid_gid_raw(
                 size_t n_supplementary_gids,
                 bool chown_stdio) {
 
+        int r;
+
         if (!uid_is_valid(uid))
                 uid = 0;
         if (!gid_is_valid(gid))
@@ -67,14 +69,9 @@ int change_uid_gid_raw(
                 (void) fchown(STDERR_FILENO, uid, gid);
         }
 
-        if (setgroups(n_supplementary_gids, supplementary_gids) < 0)
-                return log_error_errno(errno, "Failed to set auxiliary groups: %m");
-
-        if (setresgid(gid, gid, gid) < 0)
-                return log_error_errno(errno, "setresgid() failed: %m");
-
-        if (setresuid(uid, uid, uid) < 0)
-                return log_error_errno(errno, "setresuid() failed: %m");
+        r = fully_set_uid_gid(uid, gid, supplementary_gids, n_supplementary_gids);
+        if (r < 0)
+                return log_error_errno(r, "Changing privileges failed: %m");
 
         return 0;
 }
index e9c776a8c56575c440ee4d9c1aa346c3325f328c..4233ca652797775aa4e57262539dedc4be564334 100644 (file)
@@ -176,10 +176,7 @@ TEST(getpeercred_getpeergroups) {
                         test_gids = (gid_t*) gids;
                         n_test_gids = ELEMENTSOF(gids);
 
-                        assert_se(setgroups(n_test_gids, test_gids) >= 0);
-                        assert_se(setresgid(test_gid, test_gid, test_gid) >= 0);
-                        assert_se(setresuid(test_uid, test_uid, test_uid) >= 0);
-
+                        assert_se(fully_set_uid_gid(test_uid, test_gid, test_gids, n_test_gids) >= 0);
                 } else {
                         long ngroups_max;