#include "fd-util.h"
#include "log.h"
#include "macro.h"
+#include "missing_threads.h"
#include "nss-systemd.h"
#include "nss-util.h"
#include "pthread-util.h"
.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 = {
.pw_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
.pw_uid = UID_NOBODY,
.pw_gid = GID_NOBODY,
- .pw_gecos = (char*) "User Nobody",
+ .pw_gecos = (char*) "Kernel Overflow User",
.pw_dir = (char*) "/",
.pw_shell = (char*) NOLOGIN,
};
.mutex = PTHREAD_MUTEX_INITIALIZER,
};
-static void setup_logging(void) {
- /* We need a dummy function because log_parse_environment is a macro. */
- log_parse_environment();
-}
-
static void setup_logging_once(void) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
- assert_se(pthread_once(&once, setup_logging) == 0);
+ assert_se(pthread_once(&once, log_parse_environment_variables) == 0);
}
#define NSS_ENTRYPOINT_BEGIN \
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;
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;
}
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;
char *buffer, size_t buflen,
int *errnop) {
- size_t required;
-
assert(dest);
assert(src);
assert(src->gr_name);
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 += 1; /* ...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 < required) {
+ if (buflen < ALIGN(required)) {
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* String fields point into the user-provided buffer */
dest->gr_name = buffer;
dest->gr_passwd = stpcpy(dest->gr_name, src->gr_name) + 1;
- dest->gr_mem = (char **) strcpy(dest->gr_passwd, src->gr_passwd) + 1;
+ dest->gr_mem = ALIGN_PTR(stpcpy(dest->gr_passwd, src->gr_passwd) + 1);
*dest->gr_mem = NULL;
return NSS_STATUS_SUCCESS;
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;
return NSS_STATUS_NOTFOUND;
/* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("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))
return NSS_STATUS_NOTFOUND;
/* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("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)
return NSS_STATUS_NOTFOUND;
/* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (streq(name, root_spwd.sp_namp))
return copy_synthesized_spwd(spwd, &root_spwd, buffer, buflen, errnop);
return NSS_STATUS_NOTFOUND;
/* Synthesize records for root and nobody, in case they are missing from /etc/group */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (streq(name, root_group.gr_name))
return copy_synthesized_group(gr, &root_group, buffer, buflen, errnop);
return NSS_STATUS_NOTFOUND;
/* Synthesize records for root and nobody, in case they are missing from /etc/group */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (gid == root_group.gr_gid)
return copy_synthesized_group(gr, &root_group, buffer, buflen, errnop);
return NSS_STATUS_NOTFOUND;
/* Synthesize records for root and nobody, in case they are missing from /etc/group */
- if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+ if (secure_getenv_bool("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
if (streq(name, root_sgrp.sg_namp))
return copy_synthesized_sgrp(sgrp, &root_sgrp, buffer, buflen, errnop);