summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nxt_process.c')
-rw-r--r--src/nxt_process.c291
1 files changed, 26 insertions, 265 deletions
diff --git a/src/nxt_process.c b/src/nxt_process.c
index b246a58c..035f747f 100644
--- a/src/nxt_process.c
+++ b/src/nxt_process.c
@@ -14,7 +14,6 @@
#include <signal.h>
static void nxt_process_start(nxt_task_t *task, nxt_process_t *process);
-static nxt_int_t nxt_user_groups_get(nxt_task_t *task, nxt_user_cred_t *uc);
static nxt_int_t nxt_process_worker_setup(nxt_task_t *task,
nxt_process_t *process, int parentfd);
@@ -24,6 +23,12 @@ nxt_pid_t nxt_pid;
/* An original parent process pid. */
nxt_pid_t nxt_ppid;
+/* A cached process effective uid */
+nxt_uid_t nxt_euid;
+
+/* A cached process effective gid */
+nxt_gid_t nxt_egid;
+
nxt_bool_t nxt_proc_conn_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
{ 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0 },
@@ -208,8 +213,9 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
}
#if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
- if ((init->isolation.clone.flags & CLONE_NEWUSER) == CLONE_NEWUSER) {
- ret = nxt_clone_proc_map(task, pid, &init->isolation.clone);
+ if (NXT_CLONE_USER(init->isolation.clone.flags)) {
+ ret = nxt_clone_credential_map(task, pid, init->user_cred,
+ &init->isolation.clone);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
@@ -258,7 +264,7 @@ cleanup:
static void
nxt_process_start(nxt_task_t *task, nxt_process_t *process)
{
- nxt_int_t ret;
+ nxt_int_t ret, cap_setid;
nxt_port_t *port, *main_port;
nxt_thread_t *thread;
nxt_runtime_t *rt;
@@ -277,9 +283,22 @@ nxt_process_start(nxt_task_t *task, nxt_process_t *process)
nxt_random_init(&thread->random);
- if (rt->capabilities.setid && init->user_cred != NULL) {
- ret = nxt_user_cred_set(task, init->user_cred);
- if (ret != NXT_OK) {
+ cap_setid = rt->capabilities.setid;
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+ if (!cap_setid && NXT_CLONE_USER(init->isolation.clone.flags)) {
+ cap_setid = 1;
+ }
+#endif
+
+ if (cap_setid) {
+ ret = nxt_credential_setgids(task, init->user_cred);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+
+ ret = nxt_credential_setuid(task, init->user_cred);
+ if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
}
@@ -525,264 +544,6 @@ nxt_nanosleep(nxt_nsec_t ns)
}
-nxt_int_t
-nxt_user_cred_get(nxt_task_t *task, nxt_user_cred_t *uc, const char *group)
-{
- struct group *grp;
- struct passwd *pwd;
-
- nxt_errno = 0;
-
- pwd = getpwnam(uc->user);
-
- if (nxt_slow_path(pwd == NULL)) {
-
- if (nxt_errno == 0) {
- nxt_alert(task, "getpwnam(\"%s\") failed, user \"%s\" not found",
- uc->user, uc->user);
- } else {
- nxt_alert(task, "getpwnam(\"%s\") failed %E", uc->user, nxt_errno);
- }
-
- return NXT_ERROR;
- }
-
- uc->uid = pwd->pw_uid;
- uc->base_gid = pwd->pw_gid;
-
- if (group != NULL && group[0] != '\0') {
- nxt_errno = 0;
-
- grp = getgrnam(group);
-
- if (nxt_slow_path(grp == NULL)) {
-
- if (nxt_errno == 0) {
- nxt_alert(task,
- "getgrnam(\"%s\") failed, group \"%s\" not found",
- group, group);
- } else {
- nxt_alert(task, "getgrnam(\"%s\") failed %E", group, nxt_errno);
- }
-
- return NXT_ERROR;
- }
-
- uc->base_gid = grp->gr_gid;
- }
-
- return nxt_user_groups_get(task, uc);
-}
-
-
-/*
- * nxt_user_groups_get() stores an array of groups IDs which should be
- * set by the initgroups() function for a given user. The initgroups()
- * may block a just forked worker process for some time if LDAP or NDIS+
- * is used, so nxt_user_groups_get() allows to get worker user groups in
- * main process. In a nutshell the initgroups() calls getgrouplist()
- * followed by setgroups(). However Solaris lacks the getgrouplist().
- * Besides getgrouplist() does not allow to query the exact number of
- * groups while NGROUPS_MAX can be quite large (e.g. 65536 on Linux).
- * So nxt_user_groups_get() emulates getgrouplist(): at first the function
- * saves the super-user groups IDs, then calls initgroups() and saves the
- * specified user groups IDs, and then restores the super-user groups IDs.
- * This works at least on Linux, FreeBSD, and Solaris, but does not work
- * on MacOSX, getgroups(2):
- *
- * To provide compatibility with applications that use getgroups() in
- * environments where users may be in more than {NGROUPS_MAX} groups,
- * a variant of getgroups(), obtained when compiling with either the
- * macros _DARWIN_UNLIMITED_GETGROUPS or _DARWIN_C_SOURCE defined, can
- * be used that is not limited to {NGROUPS_MAX} groups. However, this
- * variant only returns the user's default group access list and not
- * the group list modified by a call to setgroups(2).
- *
- * For such cases initgroups() is used in worker process as fallback.
- */
-
-static nxt_int_t
-nxt_user_groups_get(nxt_task_t *task, nxt_user_cred_t *uc)
-{
- int nsaved, ngroups;
- nxt_int_t ret;
- nxt_gid_t *saved;
-
- nsaved = getgroups(0, NULL);
-
- if (nsaved == -1) {
- nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno);
- return NXT_ERROR;
- }
-
- nxt_debug(task, "getgroups(0, NULL): %d", nsaved);
-
- if (nsaved > NGROUPS_MAX) {
- /* MacOSX case. */
-
- uc->gids = NULL;
- uc->ngroups = 0;
-
- return NXT_OK;
- }
-
- saved = nxt_malloc(nsaved * sizeof(nxt_gid_t));
-
- if (saved == NULL) {
- return NXT_ERROR;
- }
-
- ret = NXT_ERROR;
-
- nsaved = getgroups(nsaved, saved);
-
- if (nsaved == -1) {
- nxt_alert(task, "getgroups(%d) failed %E", nsaved, nxt_errno);
- goto free;
- }
-
- nxt_debug(task, "getgroups(): %d", nsaved);
-
- if (initgroups(uc->user, uc->base_gid) != 0) {
- if (nxt_errno == NXT_EPERM) {
- nxt_log(task, NXT_LOG_NOTICE,
- "initgroups(%s, %d) failed %E, ignored",
- uc->user, uc->base_gid, nxt_errno);
-
- ret = NXT_OK;
-
- goto free;
-
- } else {
- nxt_alert(task, "initgroups(%s, %d) failed %E",
- uc->user, uc->base_gid, nxt_errno);
- goto restore;
- }
- }
-
- ngroups = getgroups(0, NULL);
-
- if (ngroups == -1) {
- nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno);
- goto restore;
- }
-
- nxt_debug(task, "getgroups(0, NULL): %d", ngroups);
-
- uc->gids = nxt_malloc(ngroups * sizeof(nxt_gid_t));
-
- if (uc->gids == NULL) {
- goto restore;
- }
-
- ngroups = getgroups(ngroups, uc->gids);
-
- if (ngroups == -1) {
- nxt_alert(task, "getgroups(%d) failed %E", ngroups, nxt_errno);
- goto restore;
- }
-
- uc->ngroups = ngroups;
-
-#if (NXT_DEBUG)
- {
- u_char *p, *end;
- nxt_uint_t i;
- u_char msg[NXT_MAX_ERROR_STR];
-
- p = msg;
- end = msg + NXT_MAX_ERROR_STR;
-
- for (i = 0; i < uc->ngroups; i++) {
- p = nxt_sprintf(p, end, "%uL:", (uint64_t) uc->gids[i]);
- }
-
- nxt_debug(task, "user \"%s\" cred: uid:%uL base gid:%uL, gids:%*s",
- uc->user, (uint64_t) uc->uid, (uint64_t) uc->base_gid,
- p - msg, msg);
- }
-#endif
-
- ret = NXT_OK;
-
-restore:
-
- if (setgroups(nsaved, saved) != 0) {
- nxt_alert(task, "setgroups(%d) failed %E", nsaved, nxt_errno);
- ret = NXT_ERROR;
- }
-
-free:
-
- nxt_free(saved);
-
- return ret;
-}
-
-
-nxt_int_t
-nxt_user_cred_set(nxt_task_t *task, nxt_user_cred_t *uc)
-{
- nxt_debug(task, "user cred set: \"%s\" uid:%d base gid:%d",
- uc->user, uc->uid, uc->base_gid);
-
- if (setgid(uc->base_gid) != 0) {
-
-#if (NXT_HAVE_CLONE)
- if (nxt_errno == EINVAL) {
- nxt_log(task, NXT_LOG_ERR, "The gid %d isn't valid in the "
- "application namespace.", uc->base_gid);
- return NXT_ERROR;
- }
-#endif
-
- nxt_alert(task, "setgid(%d) failed %E", uc->base_gid, nxt_errno);
- return NXT_ERROR;
- }
-
- if (uc->gids != NULL) {
- if (setgroups(uc->ngroups, uc->gids) != 0) {
-
-#if (NXT_HAVE_CLONE)
- if (nxt_errno == EINVAL) {
- nxt_log(task, NXT_LOG_ERR, "The user \"%s\" (uid: %d) has "
- "supplementary group ids not valid in the application "
- "namespace.", uc->user, uc->uid);
- return NXT_ERROR;
- }
-#endif
-
- nxt_alert(task, "setgroups(%i) failed %E", uc->ngroups, nxt_errno);
- return NXT_ERROR;
- }
-
- } else {
- /* MacOSX fallback. */
- if (initgroups(uc->user, uc->base_gid) != 0) {
- nxt_alert(task, "initgroups(%s, %d) failed %E",
- uc->user, uc->base_gid, nxt_errno);
- return NXT_ERROR;
- }
- }
-
- if (setuid(uc->uid) != 0) {
-
-#if (NXT_HAVE_CLONE)
- if (nxt_errno == EINVAL) {
- nxt_log(task, NXT_LOG_ERR, "The uid %d (user \"%s\") isn't "
- "valid in the application namespace.", uc->uid, uc->user);
- return NXT_ERROR;
- }
-#endif
-
- nxt_alert(task, "setuid(%d) failed %E", uc->uid, nxt_errno);
- return NXT_ERROR;
- }
-
- return NXT_OK;
-}
-
-
void
nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i)
{