]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
attach: use PR_SET_NO_NEW_PRIVS
authorChristian Brauner <christian.brauner@canonical.com>
Fri, 2 Sep 2016 16:56:48 +0000 (18:56 +0200)
committerChristian Brauner <christian.brauner@canonical.com>
Mon, 5 Sep 2016 20:56:22 +0000 (22:56 +0200)
- 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>
src/lxc/attach.c

index 813d04984dee318366bed485c847a4f99279a4e7..ac39fa2239f440c4f98af250345c865bceba6cbd 100644 (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