Isolation: allowed the use of credentials with unpriv userns.

The setuid/setgid syscalls requires root capabilities but if the kernel
supports unprivileged user namespace then the child process has the full
set of capabilities in the new namespace, then we can allow setting "user"
and "group" in such cases (this is a common security use case).

Tests were added to ensure user gets meaningful error messages for
uid/gid mapping misconfigurations.
This commit is contained in:
Tiago Natel
2019-12-06 16:52:50 +00:00
parent ed2492a66a
commit 411daeaa53
13 changed files with 1187 additions and 152 deletions

View File

@@ -280,49 +280,9 @@ free:
nxt_int_t
nxt_credential_set(nxt_task_t *task, nxt_credential_t *uc)
nxt_credential_setuid(nxt_task_t *task, nxt_credential_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;
}
}
nxt_debug(task, "user cred set: \"%s\" uid:%d", uc->user, uc->uid);
if (setuid(uc->uid) != 0) {
@@ -340,3 +300,51 @@ nxt_credential_set(nxt_task_t *task, nxt_credential_t *uc)
return NXT_OK;
}
nxt_int_t
nxt_credential_setgids(nxt_task_t *task, nxt_credential_t *uc)
{
nxt_runtime_t *rt;
nxt_debug(task, "user cred set gids: base gid:%d, ngroups: %d",
uc->base_gid, uc->ngroups);
rt = task->thread->runtime;
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 (!rt->capabilities.setid) {
return NXT_OK;
}
if (nxt_slow_path(uc->ngroups > 0
&& 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;
}
return NXT_OK;
}