From 136dc4c4350dfcb1d61ceaac982d0d0a8e6e3863 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 11:51:11 +0200 Subject: core: set $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS in ExecStop=/ExecStopPost= commands This should simplify monitoring tools for services, by passing the most basic information about service result/exit information via environment variables, thus making it unnecessary to retrieve them explicitly via the bus. --- man/systemd.exec.xml | 37 +++++++++++++++++++++++++++++++++++++ man/systemd.service.xml | 8 +++++++- 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'man') diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 58ba582911..0fc658f180 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1602,6 +1602,43 @@ functions) if their standard output or standard error output is connected to the journal anyway, thus enabling delivery of structured metadata along with logged messages. + + + $SERVICE_RESULT + + Only defined for the service unit type, this environment variable is passed to all + ExecStop= and ExecStopPost= processes, and encodes the service + "result". Currently, the following values are defined: timeout (in case of an operation + timeout), exit-code (if a service process exited with a non-zero exit code; see + $EXIT_STATUS below for the actual exit status returned), signal (if a + service process was terminated abnormally by a signal; see $EXIT_STATUS below for the actual + signal used for the termination), core-dump (if a service process terminated abnormally and + dumped core), watchdog (if the watchdog keep-alive ping was enabled for the service but it + missed the deadline), or resources (a catch-all condition in case a system operation + failed). + + This environment variable is useful to monitor failure or successful termination of a service. Even + though this variable is available in both ExecStop= and ExecStopPost=, it + is usually a better choice to place monitoring tools in the latter, as the former is only invoked for services + that managed to start up correctly, and the latter covers both services that failed during their start-up and + those which failed during their runtime. + + + + $EXIT_CODE + $EXIT_STATUS + + Only defined for the service unit type, these environment variables are passed to all + ExecStop=, ExecStopPost= processes and contain exit status/code + information of the main process of the service. For the precise definition of the exit code and status, see + wait2. $EXIT_CODE + is one of exited, killed, + dumped. $EXIT_STATUS contains the numeric exit code formatted as string + if $EXIT_CODE is exited, and the signal name in all other cases. Note + that these environment variables are only set if the service manager succeeded to start and identify the main + process of the service. + + Additional variables may be configured by the following diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 875d368fcf..e82edbe93e 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -429,7 +429,13 @@ service failed to start up correctly. Commands configured with this setting need to be able to operate even if the service failed starting up half-way and left incompletely initialized data around. As the service's processes have been terminated already when the commands specified with this setting are executed they should - not attempt to communicate with them. + not attempt to communicate with them. + + Note that all commands that are configured with this setting are invoked with the result code of the + service, as well as the main process' exit code and status, set in the $SERVICE_RESULT, + $EXIT_CODE and $EXIT_STATUS environment variables, see + systemd.exec5 for + details. -- cgit v1.2.3-54-g00ecf From 2129011e92feee93383b450bb2d20008786b90a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 13:14:01 +0200 Subject: nss-systemd: resolve root/nobody statically 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 | 22 ++++++++- man/nss-systemd.xml | 4 ++ src/nss-systemd/nss-systemd.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) (limited to 'man') diff --git a/configure.ac b/configure.ac index a86deca471..4d1c96606f 100644 --- a/configure.ac +++ b/configure.ac @@ -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} diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml index 4228372e51..56d26e7d1f 100644 --- a/man/nss-systemd.xml +++ b/man/nss-systemd.xml @@ -61,6 +61,10 @@ systemd.exec5 for details on this option. + 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 /etc/passwd or + /etc/group, or if these files are missing. + To activate the NSS module, add systemd to the lines starting with passwd: and group: in /etc/nsswitch.conf. diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index e7a4393bb0..7078c0c50c 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -26,9 +26,52 @@ #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; -- cgit v1.2.3-54-g00ecf