From: Michael Vogt Date: Tue, 23 Jan 2018 18:53:08 +0000 (+0100) Subject: sysusers: allow uid:gid in sysusers.conf files X-Git-Tag: v237~17^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4cb41413c82e81fa4f9f211b95ac5cd5c13a543b;p=thirdparty%2Fsystemd.git sysusers: allow uid:gid in sysusers.conf files This PR allows to write sysuser.conf lines like: ``` u games 5:60 - ``` This will create an a "games" user with uid 5 and games group with gid 60. This is arguable ugly, however it is required to represent certain configurations like the default passwd file on Debian and Ubuntu. When the ":" syntax is used and there is a group with the given gid already then no new group is created. This allows writing the following: ``` g unrelated 60 u games 5:60 - ``` which will create a "games" user with the uid 5 and the primary gid 60. No group games is created here (might be useful for [1]). [1] https://pagure.io/packaging-committee/issue/442 --- diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml index 38b749cf15e..a4083adb4f5 100644 --- a/man/sysusers.d.xml +++ b/man/sysusers.d.xml @@ -191,7 +191,10 @@ u root 0 "Superuser" /root in the file system. In this case, the UID/GID is read from the path's owner/group. This is useful to create users whose UID/GID match the owners of pre-existing files (such as SUID or SGID - binaries). + binaries). + The syntax uid:gid is also supported to + allow creating user and group pairs with different numeric UID and GID values. If a group with the indicated GID already exists it is not created. + For m lines, this field should contain the group name to add to a user to. diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index d8009458ee3..1845b80d492 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -64,6 +64,7 @@ typedef struct Item { uid_t uid; bool gid_set:1; + bool gid_existing_ok:1; bool uid_set:1; bool todo_user:1; @@ -1100,6 +1101,8 @@ static int add_group(Item *i) { return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); if (r == 0) { log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name); + if (i->gid_existing_ok) + return 0; i->gid_set = false; } } @@ -1551,11 +1554,18 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { path_kill_slashes(i->uid_path); } else { - r = parse_uid(resolved_id, &i->uid); - if (r < 0) { - log_error("Failed to parse UID: %s", id); - return -EBADMSG; + _cleanup_free_ char *uid = NULL, *gid = NULL; + if (split_pair(resolved_id, ":", &uid, &gid) == 0) { + r = parse_gid(gid, &i->gid); + if (r < 0) + return log_error_errno(r, "Failed to parse GID: '%s': %m", id); + i->gid_set = true; + i->gid_existing_ok = true; + free_and_replace(resolved_id, uid); } + r = parse_uid(resolved_id, &i->uid); + if (r < 0) + return log_error_errno(r, "Failed to parse UID: '%s': %m", id); i->uid_set = true; } @@ -1602,10 +1612,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { path_kill_slashes(i->gid_path); } else { r = parse_gid(resolved_id, &i->gid); - if (r < 0) { - log_error("Failed to parse GID: %s", id); - return -EBADMSG; - } + if (r < 0) + return log_error_errno(r, "Failed to parse GID: '%s': %m", id); i->gid_set = true; }