From 563dc6f8e2cda4114dd20f32655890ed378c3740 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 15 Mar 2018 18:46:28 +0100 Subject: [PATCH] sysusers: do not append entries after the NIS ones The NIS-catchall entry switches from files to NIS lookup and never goes back, so it must be the last entry in /etc/passwd (the other +/-{user,@netgroup} entries don't have to be). That's how the nss_compat mode for /etc/passwd (and /etc/group) traditionally works. It's age-old historic behaviour that the NIS entry must be the last one. It doesn't seem to be specified somewhere, but it worked like this since very early SunOS when NIS was first included. Fixes: #8467 --- src/sysusers/sysusers.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index cd273ef..5dcc213 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -396,6 +396,7 @@ static const char* default_shell(uid_t uid) { static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char **tmpfile_path) { _cleanup_fclose_ FILE *original = NULL, *passwd = NULL; _cleanup_(unlink_and_freep) char *passwd_tmp = NULL; + struct passwd *pw = NULL; Iterator iterator; Item *i; int r; @@ -409,7 +410,6 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char original = fopen(passwd_path, "re"); if (original) { - struct passwd *pw; r = sync_rights(original, passwd); if (r < 0) @@ -429,6 +429,10 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char return -EEXIST; } + /* Make sure we keep the NIS entries (if any) at the end. */ + if (IN_SET(pw->pw_name[0], '+', '-')) + break; + errno = 0; if (putpwent(pw, passwd) < 0) return errno ? -errno : -EIO; @@ -468,6 +472,17 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char return errno ? -errno : -EIO; } + /* Append the remaining NIS entries if any */ + while (pw) { + errno = 0; + if (putpwent(pw, passwd) < 0) + return errno ? -errno : -EIO; + + pw = fgetpwent(original); + } + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + r = fflush_and_check(passwd); if (r < 0) return r; @@ -567,6 +582,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** _cleanup_fclose_ FILE *original = NULL, *group = NULL; _cleanup_(unlink_and_freep) char *group_tmp = NULL; bool group_changed = false; + struct group *gr = NULL; Iterator iterator; Item *i; int r; @@ -580,7 +596,6 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** original = fopen(group_path, "re"); if (original) { - struct group *gr; r = sync_rights(original, group); if (r < 0) @@ -604,6 +619,10 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** return -EEXIST; } + /* Make sure we keep the NIS entries (if any) at the end. */ + if (IN_SET(gr->gr_name[0], '+', '-')) + break; + r = putgrent_with_members(gr, group); if (r < 0) return r; @@ -636,6 +655,17 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** group_changed = true; } + /* Append the remaining NIS entries if any */ + while (gr) { + errno = 0; + if (putgrent(gr, group) != 0) + return errno > 0 ? -errno : -EIO; + + gr = fgetgrent(original); + } + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + r = fflush_sync_and_check(group); if (r < 0) return r; -- 2.7.4