From 8a7adccbdb23ae6fee82840ef41d17d5e568a8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 19 Aug 2022 16:43:45 +0200 Subject: various: try to use DEFAULT_USER_SHELL for root too /bin/sh as a shell is punishing. There is no good reason to make the occasional root login unpleasant. Since /bin/sh is usually /bin/bash in compat mode, i.e. if one is available, the other will be too, /bin/bash is almost as good as a default. But to avoid a regression in the situation where /bin/bash (or DEFAULT_USER_SHELL) is not installed, we check with access() and fall back to /bin/sh. This should make this change in behaviour less risky. (FWIW, e.g. Fedora/RHEL use /bin/bash as default for root.) This is a follow-up of sorts for 53350c7bbade8c5f357aa3d1029ef9b2208ea675, which added the default-user-shell option, but most likely with the idea of using /bin/bash less ;) Fixes #24369. --- src/nss-systemd/nss-systemd.c | 60 ++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'src/nss-systemd') diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index e24828450f..75d749e736 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -26,7 +26,7 @@ static const struct passwd root_passwd = { .pw_gid = 0, .pw_gecos = (char*) "Super User", .pw_dir = (char*) "/root", - .pw_shell = (char*) "/bin/sh", + .pw_shell = NULL, }; static const struct spwd root_spwd = { @@ -142,24 +142,25 @@ NSS_INITGROUPS_PROTOTYPE(systemd); static enum nss_status copy_synthesized_passwd( struct passwd *dest, const struct passwd *src, + const char *fallback_shell, char *buffer, size_t buflen, int *errnop) { - size_t required; - assert(dest); assert(src); assert(src->pw_name); assert(src->pw_passwd); assert(src->pw_gecos); assert(src->pw_dir); - assert(src->pw_shell); - required = strlen(src->pw_name) + 1; - required += strlen(src->pw_passwd) + 1; - required += strlen(src->pw_gecos) + 1; - required += strlen(src->pw_dir) + 1; - required += strlen(src->pw_shell) + 1; + const char *shell = ASSERT_PTR(src->pw_shell ?: fallback_shell); + + size_t required = + strlen(src->pw_name) + 1 + + strlen(src->pw_passwd) + 1 + + strlen(src->pw_gecos) + 1 + + strlen(src->pw_dir) + 1 + + strlen(shell) + 1; if (buflen < required) { *errnop = ERANGE; @@ -176,7 +177,7 @@ static enum nss_status copy_synthesized_passwd( dest->pw_gecos = stpcpy(dest->pw_passwd, src->pw_passwd) + 1; dest->pw_dir = stpcpy(dest->pw_gecos, src->pw_gecos) + 1; dest->pw_shell = stpcpy(dest->pw_dir, src->pw_dir) + 1; - strcpy(dest->pw_shell, src->pw_shell); + strcpy(dest->pw_shell, shell); return NSS_STATUS_SUCCESS; } @@ -187,15 +188,14 @@ static enum nss_status copy_synthesized_spwd( char *buffer, size_t buflen, int *errnop) { - size_t required; - assert(dest); assert(src); assert(src->sp_namp); assert(src->sp_pwdp); - required = strlen(src->sp_namp) + 1; - required += strlen(src->sp_pwdp) + 1; + size_t required = + strlen(src->sp_namp) + 1 + + strlen(src->sp_pwdp) + 1; if (buflen < required) { *errnop = ERANGE; @@ -220,8 +220,6 @@ static enum nss_status copy_synthesized_group( char *buffer, size_t buflen, int *errnop) { - size_t required; - assert(dest); assert(src); assert(src->gr_name); @@ -229,9 +227,10 @@ static enum nss_status copy_synthesized_group( assert(src->gr_mem); assert(!*src->gr_mem); /* Our synthesized records' gr_mem is always just NULL... */ - required = strlen(src->gr_name) + 1; - required += strlen(src->gr_passwd) + 1; - required += sizeof(char*); /* ...but that NULL still needs to be stored into the buffer! */ + size_t required = + strlen(src->gr_name) + 1 + + strlen(src->gr_passwd) + 1 + + sizeof(char*); /* ...but that NULL still needs to be stored into the buffer! */ if (buflen < ALIGN(required)) { *errnop = ERANGE; @@ -257,15 +256,14 @@ static enum nss_status copy_synthesized_sgrp( char *buffer, size_t buflen, int *errnop) { - size_t required; - assert(dest); assert(src); assert(src->sg_namp); assert(src->sg_passwd); - required = strlen(src->sg_namp) + 1; - required += strlen(src->sg_passwd) + 1; + size_t required = + strlen(src->sg_namp) + 1 + + strlen(src->sg_passwd) + 1; if (buflen < required) { *errnop = ERANGE; @@ -310,13 +308,17 @@ enum nss_status _nss_systemd_getpwnam_r( if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (streq(name, root_passwd.pw_name)) - return copy_synthesized_passwd(pwd, &root_passwd, buffer, buflen, errnop); + return copy_synthesized_passwd(pwd, &root_passwd, + default_root_shell(NULL), + buffer, buflen, errnop); if (streq(name, nobody_passwd.pw_name)) { if (!synthesize_nobody()) return NSS_STATUS_NOTFOUND; - return copy_synthesized_passwd(pwd, &nobody_passwd, buffer, buflen, errnop); + return copy_synthesized_passwd(pwd, &nobody_passwd, + NULL, + buffer, buflen, errnop); } } else if (STR_IN_SET(name, root_passwd.pw_name, nobody_passwd.pw_name)) @@ -354,13 +356,17 @@ enum nss_status _nss_systemd_getpwuid_r( if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (uid == root_passwd.pw_uid) - return copy_synthesized_passwd(pwd, &root_passwd, buffer, buflen, errnop); + return copy_synthesized_passwd(pwd, &root_passwd, + default_root_shell(NULL), + buffer, buflen, errnop); if (uid == nobody_passwd.pw_uid) { if (!synthesize_nobody()) return NSS_STATUS_NOTFOUND; - return copy_synthesized_passwd(pwd, &nobody_passwd, buffer, buflen, errnop); + return copy_synthesized_passwd(pwd, &nobody_passwd, + NULL, + buffer, buflen, errnop); } } else if (uid == root_passwd.pw_uid || uid == nobody_passwd.pw_uid) -- cgit v1.2.1