]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nss-systemd: resolve root/nobody statically
authorLennart Poettering <lennart@poettering.net>
Wed, 27 Jul 2016 11:14:01 +0000 (13:14 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Aug 2016 21:08:05 +0000 (23:08 +0200)
Let's extend nss-systemd to also synthesize user/group entries for the
UIDs/GIDs 0 and 65534 which have special kernel meaning. Given that nss-systemd
is listed in /etc/nsswitch.conf only very late any explicit listing in
/etc/passwd or /etc/group takes precedence.

This functionality is useful in minimal container-like setups that lack
/etc/passwd files (or only have incompletely populated ones).

configure.ac
man/nss-systemd.xml
src/nss-systemd/nss-systemd.c

index a86deca471dc6565026c7ba8c427c97aae465313..4d1c96606f09ef2bf888d3b67e646d3c387eec4b 100644 (file)
@@ -556,12 +556,30 @@ AC_SUBST(CERTIFICATEROOT)
 
 AC_ARG_WITH([support-url],
         AS_HELP_STRING([--with-support-url=URL],
-                [Specify the supoport URL to show in catalog entries included in systemd]),
+                [Specify the support URL to show in catalog entries included in systemd]),
         [SUPPORT_URL="$withval"],
         [SUPPORT_URL=http://lists.freedesktop.org/mailman/listinfo/systemd-devel])
 
 AC_SUBST(SUPPORT_URL)
 
+AC_ARG_WITH([nobody-user],
+        AS_HELP_STRING([--with-nobody-user=NAME],
+                [Specify the name of the nobody user (the one with UID 65534)]),
+        [NOBODY_USER_NAME="$withval"],
+        [NOBODY_USER_NAME=nobody])
+
+AC_SUBST(NOBODY_USER_NAME)
+AC_DEFINE_UNQUOTED(NOBODY_USER_NAME, ["$NOBODY_USER_NAME"], [The name of the nobody user (the one with UID 65534)])
+
+AC_ARG_WITH([nobody-group],
+        AS_HELP_STRING([--with-nobody-group=NAME],
+                [Specify the name of the nobody group (the one with GID 65534)]),
+        [NOBODY_GROUP_NAME="$withval"],
+        [NOBODY_GROUP_NAME=nobody])
+
+AC_SUBST(NOBODY_GROUP_NAME)
+AC_DEFINE_UNQUOTED(NOBODY_GROUP_NAME, ["$NOBODY_GROUP_NAME"], [The name of the nobody group (the one with GID 65534)])
+
 # ------------------------------------------------------------------------------
 have_xz=no
 AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [Disable optional XZ support]))
@@ -1677,6 +1695,8 @@ AC_MSG_RESULT([
         Maximum System GID:                ${SYSTEM_GID_MAX}
         Certificate root:                  ${CERTIFICATEROOT}
         Support URL:                       ${SUPPORT_URL}
+        Nobody User Name:                  ${NOBODY_USER_NAME}
+        Nobody Group Name:                 ${NOBODY_GROUP_NAME}
 
         CFLAGS:   ${OUR_CFLAGS} ${CFLAGS}
         CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
index 4228372e51d982742c2c8ab6cdbcec13d2226fba..56d26e7d1f9ea049c97bb37f43d9caa9a21892f7 100644 (file)
     <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details on
     this option.</para>
 
+    <para>This module also ensures that the root and nobody users and groups (i.e. the users/groups with the UIDs/GIDs
+    0 and 65534) remain resolvable at all times, even if they aren't listed in <filename>/etc/passwd</filename> or
+    <filename>/etc/group</filename>, or if these files are missing.</para>
+
     <para>To activate the NSS module, add <literal>systemd</literal> to the lines starting with
     <literal>passwd:</literal> and <literal>group:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
 
index e7a4393bb0e007b1407601d7384fa6d5cdd019c5..7078c0c50cc51eaa9c0828d73fa6c6953a708281 100644 (file)
 #include "macro.h"
 #include "nss-util.h"
 #include "signal-util.h"
+#include "string-util.h"
 #include "user-util.h"
 #include "util.h"
 
+#ifndef NOBODY_USER_NAME
+#define NOBODY_USER_NAME "nobody"
+#endif
+
+#ifndef NOBODY_GROUP_NAME
+#define NOBODY_GROUP_NAME "nobody"
+#endif
+
+static const struct passwd root_passwd = {
+        .pw_name = (char*) "root",
+        .pw_passwd = (char*) "x", /* see shadow file */
+        .pw_uid = 0,
+        .pw_gid = 0,
+        .pw_gecos = (char*) "Super User",
+        .pw_dir = (char*) "/root",
+        .pw_shell = (char*) "/bin/sh",
+};
+
+static const struct passwd nobody_passwd = {
+        .pw_name = (char*) NOBODY_USER_NAME,
+        .pw_passwd = (char*) "*", /* locked */
+        .pw_uid = 65534,
+        .pw_gid = 65534,
+        .pw_gecos = (char*) "User Nobody",
+        .pw_dir = (char*) "/",
+        .pw_shell = (char*) "/sbin/nologin",
+};
+
+static const struct group root_group = {
+        .gr_name = (char*) "root",
+        .gr_gid = 0,
+        .gr_passwd = (char*) "x", /* see shadow file */
+        .gr_mem = (char*[]) { NULL },
+};
+
+static const struct group nobody_group = {
+        .gr_name = (char*) NOBODY_GROUP_NAME,
+        .gr_gid = 65534,
+        .gr_passwd = (char*) "*", /* locked */
+        .gr_mem = (char*[]) { NULL },
+};
+
 NSS_GETPW_PROTOTYPES(systemd);
 NSS_GETGR_PROTOTYPES(systemd);
 
@@ -50,6 +93,23 @@ enum nss_status _nss_systemd_getpwnam_r(
         assert(name);
         assert(pwd);
 
+        if (!valid_user_group_name(name)) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        /* 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;
+        }
+
         /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
         if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                 goto not_found;
@@ -126,6 +186,18 @@ enum nss_status _nss_systemd_getpwuid_r(
                 goto fail;
         }
 
+        /* 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 (uid <= SYSTEM_UID_MAX)
                 goto not_found;
 
@@ -202,6 +274,23 @@ enum nss_status _nss_systemd_getgrnam_r(
         assert(name);
         assert(gr);
 
+        if (!valid_user_group_name(name)) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        /* 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_DYNAMIC_BYPASS") > 0)
                 goto not_found;
 
@@ -275,6 +364,18 @@ enum nss_status _nss_systemd_getgrgid_r(
                 goto fail;
         }
 
+        /* 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 (gid <= SYSTEM_GID_MAX)
                 goto not_found;