Skip to content

Commit

Permalink
attach: handle id switching smarter
Browse files Browse the repository at this point in the history
For setup, switch to the most privileged ids we can find. That is either
nsuid 0 if a mapping has been established if not switch to the ids the
init running in the container was started with.
After setup, switch to the actual requested ids.

Closes #2591.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Sep 11, 2018
1 parent db2d1af commit 936efc7
Showing 1 changed file with 37 additions and 15 deletions.
52 changes: 37 additions & 15 deletions src/lxc/attach.c
Expand Up @@ -749,6 +749,8 @@ static int attach_child_main(struct attach_clone_payload *payload)
int fd, lsm_fd, ret;
uid_t new_uid;
gid_t new_gid;
uid_t ns_root_uid = 0;
gid_t ns_root_gid = 0;
lxc_attach_options_t* options = payload->options;
struct lxc_proc_context_info* init_ctx = payload->init_ctx;
bool needs_lsm = (options->namespaces & CLONE_NEWNS) &&
Expand Down Expand Up @@ -836,25 +838,23 @@ static int attach_child_main(struct attach_clone_payload *payload)
goto on_error;
}

/* Set {u,g}id. */
new_uid = 0;
new_gid = 0;
if (options->namespaces & CLONE_NEWUSER) {
/* Check whether nsuid 0 has a mapping. */
ns_root_uid = get_ns_uid(0);

/* Ignore errors, we will fall back to root in that case (/proc was not
* mounted etc.).
*/
if (options->namespaces & CLONE_NEWUSER)
lxc_attach_get_init_uidgid(&new_uid, &new_gid);
/* Check whether nsgid 0 has a mapping. */
ns_root_gid = get_ns_gid(0);

if (options->uid != (uid_t)-1)
new_uid = options->uid;
/* If there's no mapping for nsuid 0 try to retrieve the nsuid
* init was started with.
*/
if (ns_root_uid == LXC_INVALID_UID)
lxc_attach_get_init_uidgid(&ns_root_uid, &ns_root_gid);

if (options->gid != (gid_t)-1)
new_gid = options->gid;
if (ns_root_uid == LXC_INVALID_UID)
goto on_error;

/* Try to set the {u,g}id combination. */
if (new_uid != 0 || new_gid != 0 || options->namespaces & CLONE_NEWUSER) {
ret = lxc_switch_uid_gid(new_uid, new_gid);
ret = lxc_switch_uid_gid(ns_root_uid, ns_root_gid);
if (ret < 0)
goto on_error;
}
Expand All @@ -863,6 +863,17 @@ static int attach_child_main(struct attach_clone_payload *payload)
if (ret < 0 && errno != EPERM)
goto on_error;

/* Set {u,g}id. */
if (options->uid != LXC_INVALID_UID)
new_uid = options->uid;
else
new_uid = ns_root_uid;

if (options->gid != LXC_INVALID_GID)
new_gid = options->gid;
else
new_gid = ns_root_gid;

if ((init_ctx->container && init_ctx->container->lxc_conf &&
init_ctx->container->lxc_conf->no_new_privs) ||
(options->attach_flags & LXC_ATTACH_NO_NEW_PRIVS)) {
Expand Down Expand Up @@ -952,6 +963,17 @@ static int attach_child_main(struct attach_clone_payload *payload)
TRACE("Prepared terminal file descriptor %d", payload->terminal_slave_fd);
}

/* Avoid unnecessary syscalls. */
if (new_uid == ns_root_uid)
new_uid = LXC_INVALID_UID;

if (new_gid == ns_root_gid)
new_gid = LXC_INVALID_GID;

ret = lxc_switch_uid_gid(new_uid, new_gid);
if (ret < 0)
goto on_error;

/* We're done, so we can now do whatever the user intended us to do. */
_exit(payload->exec_function(payload->exec_payload));

Expand Down

0 comments on commit 936efc7

Please sign in to comment.