return 0;
}
-static int get_group_creds(const char *groupname, gid_t *gid) {
- struct group *g;
- unsigned long lu;
-
- assert(groupname);
- assert(gid);
-
- /* We enforce some special rules for gid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(groupname, "root") || streq(groupname, "0")) {
- *gid = 0;
- return 0;
- }
-
- if (safe_atolu(groupname, &lu) >= 0) {
- errno = 0;
- g = getgrgid((gid_t) lu);
- } else {
- errno = 0;
- g = getgrnam(groupname);
- }
-
- if (!g)
- return errno != 0 ? -errno : -ESRCH;
-
- *gid = g->gr_gid;
- return 0;
-}
-
-static int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
- struct passwd *p;
- unsigned long lu;
-
- assert(username);
- assert(*username);
- assert(uid);
- assert(gid);
- assert(home);
-
- /* We enforce some special rules for uid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(*username, "root") || streq(*username, "0")) {
- *username = "root";
- *uid = 0;
- *gid = 0;
- *home = "/root";
- return 0;
- }
-
- if (safe_atolu(*username, &lu) >= 0) {
- errno = 0;
- p = getpwuid((uid_t) lu);
-
- /* If there are multiple users with the same id, make
- * sure to leave $USER to the configured value instead
- * of the first occurrence in the database. However if
- * the uid was configured by a numeric uid, then let's
- * pick the real username from /etc/passwd. */
- if (*username && p)
- *username = p->pw_name;
- } else {
- errno = 0;
- p = getpwnam(*username);
- }
-
- if (!p)
- return errno != 0 ? -errno : -ESRCH;
-
- *uid = p->pw_uid;
- *gid = p->pw_gid;
- *home = p->pw_dir;
- return 0;
-}
-
static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
bool keep_groups = false;
int r;
if (context->group || username) {
- if (context->group)
- if ((r = get_group_creds(context->group, &gid)) < 0)
+ if (context->group) {
+ const char *g = context->group;
+
+ if ((r = get_group_creds(&g, &gid)) < 0)
return r;
+ }
/* First step, initialize groups from /etc/groups */
if (username && gid != 0) {
k = 0;
STRV_FOREACH(i, context->supplementary_groups) {
+ const char *g;
if (k >= ngroups_max) {
free(gids);
return -E2BIG;
}
- if ((r = get_group_creds(*i, gids+k)) < 0) {
+ g = *i;
+ r = get_group_creds(&g, gids+k);
+ if (r < 0) {
free(gids);
return r;
}
close_session = true;
- if ((pam_code = pam_setcred(handle, PAM_ESTABLISH_CRED | PAM_SILENT)) != PAM_SUCCESS)
- goto fail;
-
if ((!(e = pam_getenvlist(handle)))) {
pam_code = PAM_BUF_ERR;
goto fail;
/* This string must fit in 10 chars (i.e. the length
* of "/sbin/init") */
- rename_process("sd:pam");
+ rename_process("sd(PAM)");
/* Make sure we don't keep open the passed fds in this
child. We assume that otherwise only those fds are
/* Check if our parent process might already have
* died? */
if (getppid() == parent_pid) {
- if (sigwait(&ss, &sig) < 0)
- goto child_finish;
+ for (;;) {
+ if (sigwait(&ss, &sig) < 0) {
+ if (errno == EINTR)
+ continue;
+
+ goto child_finish;
+ }
- assert(sig == SIGTERM);
+ assert(sig == SIGTERM);
+ break;
+ }
}
- /* Only if our parent died we'll end the session */
+ /* If our parent died we'll end the session */
if (getppid() != parent_pid)
if ((pam_code = pam_close_session(handle, PAM_DATA_SILENT)) != PAM_SUCCESS)
goto child_finish;
* cleanups, so forget about the handle here. */
handle = NULL;
- /* Unblock SIGSUR1 again in the parent */
+ /* Unblock SIGTERM again in the parent */
if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
goto fail;
* might have opened it, but we don't want this fd around. */
closelog();
+ *pam_env = e;
+ e = NULL;
+
return 0;
fail:
/* This string must fit in 10 chars (i.e. the length
* of "/sbin/init") */
- rename_process("sd.exec");
+ rename_process("sd(EXEC)");
/* We reset exactly these signals, since they are the
* only ones we set to SIG_IGN in the main daemon. All
}
}
-#ifdef HAVE_PAM
- if (context->pam_name && username) {
- if (setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds) < 0) {
- r = EXIT_PAM;
- goto fail_child;
- }
- }
-#endif
-
if (apply_permissions)
if (enforce_groups(context, username, uid) < 0) {
r = EXIT_GROUP;
umask(context->umask);
+#ifdef HAVE_PAM
+ if (context->pam_name && username) {
+ if (setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds) != 0) {
+ r = EXIT_PAM;
+ goto fail_child;
+ }
+ }
+#endif
+
if (strv_length(context->read_write_dirs) > 0 ||
strv_length(context->read_only_dirs) > 0 ||
strv_length(context->inaccessible_dirs) > 0 ||