attach: use PR_SET_NO_NEW_PRIVS

- When we detect that the container, we want to attach to, has been stared with
  PR_SET_NO_NEW_PRIVS we attach with PR_SET_NO_NEW_PRIVS as well. (We might
  relax this restriction later but let's be strict for now.)
- When LXC_ATTACH_NO_NEW_PRIVS is set in the flags passed to
  lxc_attach()/attach_child_main() then we set PR_SET_NO_NEW_PRIVS irrespective
  of whether the container was started with PR_SET_NO_NEW_PRIVS or not.
- Set no_new_privs before lsm and seccomp. We probably don't want attach() to
  be able to change the lsm or seccomp policy if the container was started with
  PR_SET_NO_NEW_PRIVS enabled.

Signed-off-by: Christian Brauner <christian.brauner@canonical.com>
This commit is contained in:
Christian Brauner 2016-09-02 18:56:48 +02:00
parent ff07d7bb5a
commit 2e812c16a5
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D

View File

@ -668,7 +668,7 @@ static bool fetch_seccomp(struct lxc_proc_context_info *i,
c = i->container;
/* Initialize an empty lxc_conf */
/* Remove current setting. */
if (!c->set_config_item(c, "lxc.seccomp", "")) {
return false;
}
@ -692,6 +692,37 @@ static bool fetch_seccomp(struct lxc_proc_context_info *i,
return false;
}
INFO("Retrieved seccomp policy.");
return true;
}
static bool no_new_privs(struct lxc_proc_context_info *ctx,
lxc_attach_options_t *options)
{
struct lxc_container *c;
char *val;
c = ctx->container;
/* Remove current setting. */
if (!c->set_config_item(c, "lxc.no_new_privs", "")) {
return false;
}
/* Retrieve currently active setting. */
val = c->get_running_config_item(c, "lxc.no_new_privs");
if (!val) {
INFO("Failed to get running config item for lxc.no_new_privs.");
return false;
}
/* Set currently active setting. */
if (!c->set_config_item(c, "lxc.no_new_privs", val)) {
free(val);
return false;
}
free(val);
return true;
}
@ -748,6 +779,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
if (!fetch_seccomp(init_ctx, options))
WARN("Failed to get seccomp policy");
if (!no_new_privs(init_ctx, options))
WARN("Could not determine whether PR_SET_NO_NEW_PRIVS is set.");
cwd = getcwd(NULL, 0);
/* determine which namespaces the container was created with
@ -1147,6 +1181,19 @@ static int attach_child_main(void* data)
shutdown(ipc_socket, SHUT_RDWR);
close(ipc_socket);
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)) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
SYSERROR("PR_SET_NO_NEW_PRIVS could not be set. "
"Process can use execve() gainable "
"privileges.");
rexit(-1);
}
INFO("PR_SET_NO_NEW_PRIVS is set. Process cannot use execve() "
"gainable privileges.");
}
/* set new apparmor profile/selinux context */
if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
int on_exec;
@ -1162,7 +1209,6 @@ static int attach_child_main(void* data)
ERROR("Loading seccomp policy");
rexit(-1);
}
lxc_proc_put_context_info(init_ctx);
/* The following is done after the communication socket is