]> git.proxmox.com Git - mirror_lxc.git/commitdiff
attach: Support unprivileged containers
authorStéphane Graber <stgraber@ubuntu.com>
Mon, 20 Jan 2014 20:26:15 +0000 (15:26 -0500)
committerStéphane Graber <stgraber@ubuntu.com>
Tue, 21 Jan 2014 04:10:24 +0000 (23:10 -0500)
This change makes lxc-attach and the matching API functions work
properly with unprivileged containers.

The trick needed to make that possible was to always start with the
userns when attaching and also relocate the cgroup management code so
that the intermediate process is moved to the cgroup before attaching to
the container's namespace as doing so later would fail due to missing
permissions.

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/attach.c
src/lxc/lxc_attach.c
src/lxc/lxccontainer.c

index de325497b82727f2870a6e749ac503dd203dfb40..3ee1d4d1c6eeccd8f4661515087ac697d7b7f8ea 100644 (file)
@@ -144,10 +144,10 @@ static int lxc_attach_to_ns(pid_t pid, int which)
         * the file for user namepsaces in /proc/$pid/ns will be called
         * 'user' once the kernel supports it
         */
-       static char *ns[] = { "mnt", "pid", "uts", "ipc", "user", "net" };
+       static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net" };
        static int flags[] = {
-               CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
-               CLONE_NEWUSER, CLONE_NEWNET
+               CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
+               CLONE_NEWNET
        };
        static const int size = sizeof(ns) / sizeof(char *);
        int fd[size];
@@ -593,7 +593,7 @@ static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_D
 int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process)
 {
        int ret, status;
-       pid_t init_pid, pid, attached_pid;
+       pid_t init_pid, pid, attached_pid, expected;
        struct lxc_proc_context_info *init_ctx;
        char* cwd;
        char* new_cwd;
@@ -689,7 +689,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
        if (pid) {
                pid_t to_cleanup_pid = pid;
-               int expected = 0;
 
                /* inital thread, we close the socket that is for the
                 * subprocesses
@@ -697,6 +696,44 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                close(ipc_sockets[1]);
                free(cwd);
 
+               /* attach to cgroup, if requested */
+               if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
+                       struct cgroup_meta_data *meta_data;
+                       struct cgroup_process_info *container_info;
+
+                       meta_data = lxc_cgroup_load_meta();
+                       if (!meta_data) {
+                               ERROR("could not move attached process %ld to cgroup of container", (long)pid);
+                               goto cleanup_error;
+                       }
+
+                       container_info = lxc_cgroup_get_container_info(name, lxcpath, meta_data);
+                       lxc_cgroup_put_meta(meta_data);
+                       if (!container_info) {
+                               ERROR("could not move attached process %ld to cgroup of container", (long)pid);
+                               goto cleanup_error;
+                       }
+
+                       /*
+                        * TODO - switch over to using a cgroup_operation.  We can't use
+                        * cgroup_enter() as that takes a handler.
+                        */
+                       ret = lxc_cgroupfs_enter(container_info, pid, false);
+                       lxc_cgroup_process_info_free(container_info);
+                       if (ret < 0) {
+                               ERROR("could not move attached process %ld to cgroup of container", (long)pid);
+                               goto cleanup_error;
+                       }
+               }
+
+               /* Let the child process know to go ahead */
+               status = 0;
+               ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
+               if (ret <= 0) {
+                       ERROR("error using IPC to notify attached process for initialization (0)");
+                       goto cleanup_error;
+               }
+
                /* get pid from intermediate process */
                ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL);
                if (ret <= 0) {
@@ -730,36 +767,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                        goto cleanup_error;
                }
 
-               /* attach to cgroup, if requested */
-               if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
-                       struct cgroup_meta_data *meta_data;
-                       struct cgroup_process_info *container_info;
-
-                       meta_data = lxc_cgroup_load_meta();
-                       if (!meta_data) {
-                               ERROR("could not move attached process %ld to cgroup of container", (long)attached_pid);
-                               goto cleanup_error;
-                       }
-
-                       container_info = lxc_cgroup_get_container_info(name, lxcpath, meta_data);
-                       lxc_cgroup_put_meta(meta_data);
-                       if (!container_info) {
-                               ERROR("could not move attached process %ld to cgroup of container", (long)attached_pid);
-                               goto cleanup_error;
-                       }
-
-                       /*
-                        * TODO - switch over to using a cgroup_operation.  We can't use
-                        * cgroup_enter() as that takes a handler.
-                        */
-                       ret = lxc_cgroupfs_enter(container_info, attached_pid, false);
-                       lxc_cgroup_process_info_free(container_info);
-                       if (ret < 0) {
-                               ERROR("could not move attached process %ld to cgroup of container", (long)attached_pid);
-                               goto cleanup_error;
-                       }
-               }
-
                /* tell attached process we're done */
                status = 2;
                ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
@@ -798,6 +805,16 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
         */
        close(ipc_sockets[0]);
 
+       /* Wait for the parent to have setup cgroups */
+       expected = 0;
+       status = -1;
+       ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status), &expected);
+       if (ret <= 0) {
+               ERROR("error communicating with child process");
+               shutdown(ipc_sockets[1], SHUT_RDWR);
+               rexit(-1);
+       }
+
        /* attach now, create another subprocess later, since pid namespaces
         * only really affect the children of the current process
         */
index 1159d09580534fc9c2b3117d7e1c5e1517c5c899..6744c058726feb52cdedbec38b0d2d74f263052b 100644 (file)
@@ -188,11 +188,6 @@ int main(int argc, char *argv[])
        lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
        lxc_attach_command_t command;
 
-        if (geteuid() != 0) {
-                ERROR("lxc-attach is not currently supported with unprivileged containers");
-                return -1;
-        }
-
        ret = lxc_caps_init();
        if (ret)
                return ret;
index 368cb46bf2a600d89e6e5e61091bfb70b79407e7..38cf24e97896e748eb33d883893951de94975e1a 100644 (file)
@@ -2567,11 +2567,6 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio
        if (!c)
                return -1;
 
-       if (am_unpriv()) {
-               ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
-               return -1;
-       }
-
        return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
 }
 
@@ -2584,11 +2579,6 @@ static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t
        if (!c)
                return -1;
 
-       if (am_unpriv()) {
-               ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
-               return -1;
-       }
-
        command.program = (char*)program;
        command.argv = (char**)argv;
        r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);