From 2e812c16a502b03abe79ee00025de50d1928ad5e Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 2 Sep 2016 18:56:48 +0200 Subject: [PATCH] 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 --- src/lxc/attach.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 813d04984..ac39fa223 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -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