]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/start.c
coverity: #1435805
[mirror_lxc.git] / src / lxc / start.c
index ce5cb3366e1d75a90566b7dc4bbf16a3d9e89b17..638e195d6356573d38738d5cd50c743e293ebf54 100644 (file)
@@ -32,6 +32,7 @@
 #include <fcntl.h>
 #include <grp.h>
 #include <poll.h>
+#include <pthread.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "terminal.h"
 #include "utils.h"
 
+#ifndef HAVE_STRLCPY
+#include "include/strlcpy.h"
+#endif
+
 lxc_log_define(lxc_start, lxc);
 
 extern void mod_all_rdeps(struct lxc_container *c, bool inc);
@@ -310,7 +315,7 @@ static int setup_signal_fd(sigset_t *oldmask)
                        return -EBADF;
        }
 
-       ret = sigprocmask(SIG_BLOCK, &mask, oldmask);
+       ret = pthread_sigmask(SIG_BLOCK, &mask, oldmask);
        if (ret < 0) {
                SYSERROR("Failed to set signal mask");
                return -EBADF;
@@ -410,6 +415,7 @@ static int signal_handler(int fd, uint32_t events, void *data,
 int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
                            lxc_state_t state)
 {
+       size_t retlen;
        ssize_t ret;
        struct lxc_list *cur, *next;
        struct lxc_state_client *client;
@@ -427,8 +433,9 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
                return 0;
        }
 
-       strncpy(msg.name, name, sizeof(msg.name));
-       msg.name[sizeof(msg.name) - 1] = 0;
+       retlen = strlcpy(msg.name, name, sizeof(msg.name));
+       if (retlen >= sizeof(msg.name))
+               return -E2BIG;
 
        lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
                client = cur->elem;
@@ -843,11 +850,18 @@ int lxc_init(const char *name, struct lxc_handler *handler)
        }
        TRACE("Chowned console");
 
+       handler->cgroup_ops = cgroup_init(handler);
+       if (!handler->cgroup_ops) {
+               ERROR("Failed to initialize cgroup driver");
+               goto out_restore_sigmask;
+       }
+       TRACE("Initialized cgroup driver");
+
        INFO("Container \"%s\" is initialized", name);
        return 0;
 
 out_restore_sigmask:
-       sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+       pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
 out_delete_tty:
        lxc_delete_tty(&conf->ttys);
 out_aborting:
@@ -865,6 +879,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
        struct lxc_list *cur, *next;
        char *namespaces[LXC_NS_MAX + 1];
        size_t namespace_count = 0;
+       struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
 
        /* The STOPPING state is there for future cleanup code which can take
         * awhile.
@@ -929,7 +944,8 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
        while (namespace_count--)
                free(namespaces[namespace_count]);
 
-       cgroup_destroy(handler);
+       cgroup_ops->destroy(cgroup_ops, handler);
+       cgroup_exit(cgroup_ops);
 
        if (handler->conf->reboot == 0) {
                /* For all new state clients simply close the command socket.
@@ -971,7 +987,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
        }
 
        /* Reset mask set by setup_signal_fd. */
-       ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+       ret = pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
        if (ret < 0)
                WARN("%s - Failed to restore signal mask", strerror(errno));
 
@@ -1043,7 +1059,13 @@ static int do_start(void *data)
                goto out_warn_father;
        }
 
-       ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+       ret = lxc_ambient_caps_up();
+       if (ret < 0) {
+               SYSERROR("Failed to raise ambient capabilities");
+               goto out_warn_father;
+       }
+
+       ret = pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
        if (ret < 0) {
                SYSERROR("Failed to set signal mask");
                goto out_warn_father;
@@ -1075,7 +1097,7 @@ static int do_start(void *data)
         */
        ret = lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE);
        if (ret < 0)
-               return -1;
+               goto out_error;
 
        ret = lxc_network_recv_veth_names_from_parent(handler);
        if (ret < 0) {
@@ -1342,6 +1364,12 @@ static int do_start(void *data)
        if (ret < 0)
                goto out_warn_father;
 
+       ret = lxc_ambient_caps_down();
+       if (ret < 0) {
+               SYSERROR("Failed to clear ambient capabilities");
+               goto out_warn_father;
+       }
+
        /* After this call, we are in error because this ops should not return
         * as it execs.
         */
@@ -1458,8 +1486,16 @@ static inline int do_share_ns(void *arg)
                        continue;
 
                ret = setns(handler->nsfd[i], 0);
-               if (ret < 0)
+               if (ret < 0) {
+                       /*
+                        * Note that joining a user and/or mount namespace
+                        * requires the process is not multithreaded otherwise
+                        * setns() will fail here.
+                        */
+                       SYSERROR("Failed to inherit %s namespace",
+                                ns_info[i].proc_name);
                        return -1;
+               }
 
                DEBUG("Inherited %s namespace", ns_info[i].proc_name);
        }
@@ -1488,8 +1524,9 @@ static int lxc_spawn(struct lxc_handler *handler)
        struct lxc_list *id_map;
        const char *name = handler->name;
        const char *lxcpath = handler->lxcpath;
-       bool cgroups_connected = false, share_ns = false;
+       bool share_ns = false;
        struct lxc_conf *conf = handler->conf;
+       struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
 
        id_map = &conf->id_map;
        wants_to_map_ids = !lxc_list_empty(id_map);
@@ -1549,14 +1586,7 @@ static int lxc_spawn(struct lxc_handler *handler)
                }
        }
 
-       if (!cgroup_init(handler)) {
-               ERROR("Failed initializing cgroup support");
-               goto out_delete_net;
-       }
-
-       cgroups_connected = true;
-
-       if (!cgroup_create(handler)) {
+       if (!cgroup_ops->create(cgroup_ops, handler)) {
                ERROR("Failed creating cgroups");
                goto out_delete_net;
        }
@@ -1645,15 +1675,15 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (ret < 0)
                goto out_delete_net;
 
-       if (!cgroup_setup_limits(handler, false)) {
+       if (!cgroup_ops->setup_limits(cgroup_ops, handler->conf, false)) {
                ERROR("Failed to setup cgroup limits for container \"%s\"", name);
                goto out_delete_net;
        }
 
-       if (!cgroup_enter(handler))
+       if (!cgroup_ops->enter(cgroup_ops, handler->pid))
                goto out_delete_net;
 
-       if (!cgroup_chown(handler))
+       if (!cgroup_ops->chown(cgroup_ops, handler->conf))
                goto out_delete_net;
 
        /* Now we're ready to preserve the network namespace */
@@ -1718,15 +1748,12 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (ret < 0)
                goto out_delete_net;
 
-       if (!cgroup_setup_limits(handler, true)) {
+       if (!cgroup_ops->setup_limits(cgroup_ops, handler->conf, true)) {
                ERROR("Failed to setup legacy device cgroup controller limits");
                goto out_delete_net;
        }
        TRACE("Set up legacy device cgroup controller limits");
 
-       cgroup_disconnect();
-       cgroups_connected = false;
-
        if (handler->ns_clone_flags & CLONE_NEWCGROUP) {
                /* Now we're ready to preserve the cgroup namespace */
                ret = lxc_try_preserve_ns(handler->pid, "cgroup");
@@ -1803,9 +1830,6 @@ static int lxc_spawn(struct lxc_handler *handler)
        return 0;
 
 out_delete_net:
-       if (cgroups_connected)
-               cgroup_disconnect();
-
        if (handler->ns_clone_flags & CLONE_NEWNET)
                lxc_delete_network(handler);