From fe102d6ab15731a199a7ea9f38c4f68d8959f86c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Sep 2017 06:20:39 +0200 Subject: [PATCH] nss-systemd,sysusers: make sure sysusers doesn't get confused by nss-systemd (#6812) In nss-systemd we synthesize user entries for "nobody" and "root", as fallback if we boot up with an entirely empty /etc. This is supposed to be a fallback only though, and it's intended that both users exists regularly in /etc/passwd + /etc/group. Before this patch systemd-sysusers would never create the entries however as it notices the synthetic entries. Let's add a way how systemd-sysusers can tell nss-systemd not to synthesize the entries for itself. Fixes: #6808 --- src/nss-systemd/nss-systemd.c | 80 +++++++++++++++++++---------------- src/sysusers/sysusers.c | 10 +++++ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index f404755dac1..37745b31039 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -129,15 +129,17 @@ enum nss_status _nss_systemd_getpwnam_r( goto not_found; /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ - if (streq(name, root_passwd.pw_name)) { - *pwd = root_passwd; - *errnop = 0; - return NSS_STATUS_SUCCESS; - } - if (streq(name, nobody_passwd.pw_name)) { - *pwd = nobody_passwd; - *errnop = 0; - return NSS_STATUS_SUCCESS; + if (getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (streq(name, root_passwd.pw_name)) { + *pwd = root_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (streq(name, nobody_passwd.pw_name)) { + *pwd = nobody_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } } /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ @@ -231,15 +233,17 @@ enum nss_status _nss_systemd_getpwuid_r( goto not_found; /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */ - if (uid == root_passwd.pw_uid) { - *pwd = root_passwd; - *errnop = 0; - return NSS_STATUS_SUCCESS; - } - if (uid == nobody_passwd.pw_uid) { - *pwd = nobody_passwd; - *errnop = 0; - return NSS_STATUS_SUCCESS; + if (getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (uid == root_passwd.pw_uid) { + *pwd = root_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (uid == nobody_passwd.pw_uid) { + *pwd = nobody_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } } if (uid <= SYSTEM_UID_MAX) @@ -331,15 +335,17 @@ enum nss_status _nss_systemd_getgrnam_r( goto not_found; /* Synthesize records for root and nobody, in case they are missing form /etc/group */ - if (streq(name, root_group.gr_name)) { - *gr = root_group; - *errnop = 0; - return NSS_STATUS_SUCCESS; - } - if (streq(name, nobody_group.gr_name)) { - *gr = nobody_group; - *errnop = 0; - return NSS_STATUS_SUCCESS; + if (getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (streq(name, root_group.gr_name)) { + *gr = root_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (streq(name, nobody_group.gr_name)) { + *gr = nobody_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } } if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) @@ -430,15 +436,17 @@ enum nss_status _nss_systemd_getgrgid_r( goto not_found; /* Synthesize records for root and nobody, in case they are missing from /etc/group */ - if (gid == root_group.gr_gid) { - *gr = root_group; - *errnop = 0; - return NSS_STATUS_SUCCESS; - } - if (gid == nobody_group.gr_gid) { - *gr = nobody_group; - *errnop = 0; - return NSS_STATUS_SUCCESS; + if (getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (gid == root_group.gr_gid) { + *gr = root_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (gid == nobody_group.gr_gid) { + *gr = nobody_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } } if (gid <= SYSTEM_GID_MAX) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index e3842192337..e9e6dae10c7 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1811,6 +1811,16 @@ int main(int argc, char *argv[]) { } } + /* Let's tell nss-systemd not to synthesize the "root" and "nobody" entries for it, so that our detection + * whether the names or UID/GID area already used otherwise doesn't get confused. After all, even though + * nss-systemd synthesizes these users/groups, they should still appear in /etc/passwd and /etc/group, as the + * synthesizing logic is merely supposed to be fallback for cases where we run with a completely unpopulated + * /etc. */ + if (setenv("SYSTEMD_NSS_BYPASS_SYNTHETIC", "1", 1) < 0) { + r = log_error_errno(errno, "Failed to set SYSTEMD_NSS_BYPASS_SYNTHETIC environment variable: %m"); + goto finish; + } + if (!uid_range) { /* Default to default range of 1..SYSTEMD_UID_MAX */ r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX);