Blob Blame History Raw
From b06ca097172783c89e04134abf16a00b5151032a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 11 Oct 2017 14:41:13 +0900
Subject: [PATCH] dynamic-user: permit the case static uid and gid are
 different

This makes systemd supports the case that DynamicUser=yes and
static user and group exist such that uid and gid of them are different.
We only refuse the operation when user does not exist but the group
with the same name exists.

Fixes #7013.

(cherry picked from commit 9ec655cbbd7505ef465e0444da0622e46099ce42)
---
 src/core/dynamic-user.c | 41 +++++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c
index a191341186..8f229d27ff 100644
--- a/src/core/dynamic-user.c
+++ b/src/core/dynamic-user.c
@@ -421,7 +421,7 @@ static void unlink_uid_lock(int lock_fd, uid_t uid, const char *name) {
         (void) make_uid_symlinks(uid, name, false); /* remove direct lookup symlinks */
 }
 
-static int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *ret) {
+static int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *ret, bool is_user) {
 
         _cleanup_close_ int etc_passwd_lock_fd = -1, uid_lock_fd = -1;
         uid_t uid = UID_INVALID;
@@ -460,19 +460,28 @@ static int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *re
                         struct passwd *p;
                         struct group *g;
 
-                        /* OK, this is not a numeric UID. Let's see if there's a user by this name */
-                        p = getpwnam(d->name);
-                        if (p)
-                                uid = p->pw_uid;
-
-                        /* Let's see if there's a group by this name */
-                        g = getgrnam(d->name);
-                        if (g) {
-                                /* If the UID/GID of the user/group of the same don't match, refuse operation */
-                                if (uid != UID_INVALID && uid != (uid_t) g->gr_gid)
-                                        return -EILSEQ;
-
-                                uid = (uid_t) g->gr_gid;
+                        if (is_user) {
+                                /* OK, this is not a numeric UID. Let's see if there's a user by this name */
+                                p = getpwnam(d->name);
+                                if (p)
+                                        uid = p->pw_uid;
+                                else {
+                                        /* if the user does not exist but the group with the same name exists, refuse operation */
+                                        g = getgrnam(d->name);
+                                        if (g)
+                                                return -EILSEQ;
+                                }
+                        } else {
+                                /* Let's see if there's a group by this name */
+                                g = getgrnam(d->name);
+                                if (g)
+                                        uid = (uid_t) g->gr_gid;
+                                else {
+                                        /* if the group does not exist but the user with the same name exists, refuse operation */
+                                        p = getpwnam(d->name);
+                                        if (p)
+                                                return -EILSEQ;
+                                }
                         }
                 }
 
@@ -814,13 +823,13 @@ int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *ui
         /* Realize both the referenced user and group */
 
         if (creds->user) {
-                r = dynamic_user_realize(creds->user, suggested_paths, &u);
+                r = dynamic_user_realize(creds->user, suggested_paths, &u, true);
                 if (r < 0)
                         return r;
         }
 
         if (creds->group && creds->group != creds->user) {
-                r = dynamic_user_realize(creds->group, suggested_paths, &g);
+                r = dynamic_user_realize(creds->group, suggested_paths, &g, false);
                 if (r < 0)
                         return r;
         } else