]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/lxccontainer.c
confile: cleanup parse_line()
[mirror_lxc.git] / src / lxc / lxccontainer.c
index 55e391870acf7bf3ee32222446a96eb09f91b51e..da18be8aa172bb7d40a005e8228295c6ca35ed21 100644 (file)
@@ -49,7 +49,7 @@
 #include "namespace.h"
 #include "network.h"
 #include "parse.h"
-#include "raw_syscalls.h"
+#include "process_utils.h"
 #include "start.h"
 #include "state.h"
 #include "storage.h"
 #include "include/strlcpy.h"
 #endif
 
-/* Define faccessat() if missing from the C library */
-#ifndef HAVE_FACCESSAT
-static int faccessat(int __fd, const char *__file, int __type, int __flag)
-{
-#ifdef __NR_faccessat
-       return syscall(__NR_faccessat, __fd, __file, __type, __flag);
-#else
-       errno = ENOSYS;
-       return -1;
-#endif
-}
-#endif
-
 lxc_log_define(lxccontainer, lxc);
 
 static bool do_lxcapi_destroy(struct lxc_container *c);
@@ -140,7 +127,7 @@ enum {
 
 static int ongoing_create(struct lxc_container *c)
 {
-       __do_close_prot_errno int fd = -EBADF;
+       __do_close int fd = -EBADF;
        __do_free char *path = NULL;
        struct flock lk = {0};
        int ret;
@@ -550,12 +537,12 @@ static bool do_lxcapi_unfreeze(struct lxc_container *c)
 
 WRAP_API(bool, lxcapi_unfreeze)
 
-static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
+static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *ptxfd)
 {
        if (!c)
                return -1;
 
-       return lxc_terminal_getfd(c, ttynum, masterfd);
+       return lxc_terminal_getfd(c, ttynum, ptxfd);
 }
 
 WRAP_API_2(int, lxcapi_console_getfd, int *, int *)
@@ -611,6 +598,26 @@ static pid_t do_lxcapi_init_pid(struct lxc_container *c)
 
 WRAP_API(pid_t, lxcapi_init_pid)
 
+static int do_lxcapi_init_pidfd(struct lxc_container *c)
+{
+       if (!c)
+               return ret_errno(EBADF);
+
+       return lxc_cmd_get_init_pidfd(c->name, c->config_path);
+}
+
+WRAP_API(int, lxcapi_init_pidfd)
+
+static int do_lxcapi_devpts_fd(struct lxc_container *c)
+{
+       if (!c)
+               return ret_errno(EBADF);
+
+       return lxc_cmd_get_devpts_fd(c->name, c->config_path);
+}
+
+WRAP_API(int, lxcapi_devpts_fd)
+
 static bool load_config_locked(struct lxc_container *c, const char *fname)
 {
        if (!c->lxc_conf)
@@ -719,7 +726,7 @@ WRAP_API_2(bool, lxcapi_wait, const char *, int)
 
 static bool am_single_threaded(void)
 {
-       DIR *dir;
+       __do_closedir DIR *dir = NULL;
        struct dirent *direntp;
        int count = 0;
 
@@ -738,7 +745,6 @@ static bool am_single_threaded(void)
                if (count > 1)
                        break;
        }
-       closedir(dir);
 
        return count == 1;
 }
@@ -834,14 +840,12 @@ static bool wait_on_daemonized_start(struct lxc_handler *handler, int pid)
                DEBUG("First child %d exited", pid);
 
        /* Close write end of the socket pair. */
-       close(handler->state_socket_pair[1]);
-       handler->state_socket_pair[1] = -1;
+       close_prot_errno_disarm(handler->state_socket_pair[1]);
 
        state = lxc_rcv_status(handler->state_socket_pair[0]);
 
        /* Close read end of the socket pair. */
-       close(handler->state_socket_pair[0]);
-       handler->state_socket_pair[0] = -1;
+       close_prot_errno_disarm(handler->state_socket_pair[0]);
 
        if (state < 0) {
                SYSERROR("Failed to receive the container state");
@@ -871,7 +875,6 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                NULL,
        };
        char **init_cmd = NULL;
-       int keepfds[3] = {-1, -1, -1};
 
        /* container does exist */
        if (!c)
@@ -905,7 +908,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
        conf = c->lxc_conf;
 
        /* initialize handler */
-       handler = lxc_init_handler(c->name, conf, c->config_path, c->daemonize);
+       handler = lxc_init_handler(NULL, c->name, conf, c->config_path, c->daemonize);
 
        container_mem_unlock(c);
        if (!handler)
@@ -922,7 +925,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
        if (!argv) {
                if (useinit) {
                        ERROR("No valid init detected");
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
                        return false;
                }
                argv = default_args;
@@ -940,7 +943,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                pid_first = fork();
                if (pid_first < 0) {
                        free_init_cmd(init_cmd);
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
                        return false;
                }
 
@@ -957,7 +960,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                        started = wait_on_daemonized_start(handler, pid_first);
 
                        free_init_cmd(init_cmd);
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
                        return started;
                }
 
@@ -989,7 +992,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                /* second parent */
                if (pid_second != 0) {
                        free_init_cmd(init_cmd);
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
                        _exit(EXIT_SUCCESS);
                }
 
@@ -1002,11 +1005,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                        _exit(EXIT_FAILURE);
                }
 
-               keepfds[0] = handler->conf->maincmd_fd;
-               keepfds[1] = handler->state_socket_pair[0];
-               keepfds[2] = handler->state_socket_pair[1];
-               ret = lxc_check_inherited(conf, true, keepfds,
-                                         sizeof(keepfds) / sizeof(keepfds[0]));
+               ret = inherit_fds(handler, true);
                if (ret < 0)
                        _exit(EXIT_FAILURE);
 
@@ -1024,7 +1023,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
        } else if (!am_single_threaded()) {
                ERROR("Cannot start non-daemonized container when threaded");
                free_init_cmd(init_cmd);
-               lxc_free_handler(handler);
+               lxc_put_handler(handler);
                return false;
        }
 
@@ -1038,7 +1037,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                w = snprintf(pidstr, sizeof(pidstr), "%d", lxc_raw_getpid());
                if (w < 0 || (size_t)w >= sizeof(pidstr)) {
                        free_init_cmd(init_cmd);
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
 
                        SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
 
@@ -1051,7 +1050,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                ret = lxc_write_to_file(c->pidfile, pidstr, w, false, 0600);
                if (ret < 0) {
                        free_init_cmd(init_cmd);
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
 
                        SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
 
@@ -1069,15 +1068,15 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                ret = unshare(CLONE_NEWNS);
                if (ret < 0) {
                        SYSERROR("Failed to unshare mount namespace");
-                       lxc_free_handler(handler);
+                       lxc_put_handler(handler);
                        ret = 1;
                        goto on_error;
                }
 
                ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
                if (ret < 0) {
-                       SYSERROR("Failed to make / rslave at startup");
-                       lxc_free_handler(handler);
+                       SYSERROR("Failed to recursively turn root mount tree into dependent mount. Continuing...");
+                       lxc_put_handler(handler);
                        ret = 1;
                        goto on_error;
                }
@@ -1086,20 +1085,16 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
 reboot:
        if (conf->reboot == REBOOT_INIT) {
                /* initialize handler */
-               handler = lxc_init_handler(c->name, conf, c->config_path, c->daemonize);
+               handler = lxc_init_handler(handler, c->name, conf, c->config_path, c->daemonize);
                if (!handler) {
                        ret = 1;
                        goto on_error;
                }
        }
 
-       keepfds[0] = handler->conf->maincmd_fd;
-       keepfds[1] = handler->state_socket_pair[0];
-       keepfds[2] = handler->state_socket_pair[1];
-       ret = lxc_check_inherited(conf, c->daemonize, keepfds,
-                                 sizeof(keepfds) / sizeof(keepfds[0]));
+       ret = inherit_fds(handler, c->daemonize);
        if (ret < 0) {
-               lxc_free_handler(handler);
+               lxc_put_handler(handler);
                ret = 1;
                goto on_error;
        }
@@ -1108,8 +1103,8 @@ reboot:
                ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
                                  c->daemonize, &c->error_num);
        else
-               ret = lxc_start(c->name, argv, handler, c->config_path,
-                               c->daemonize, &c->error_num);
+               ret = lxc_start(argv, handler, c->config_path, c->daemonize,
+                               &c->error_num);
 
        if (conf->reboot == REBOOT_REQ) {
                INFO("Container requested reboot");
@@ -1200,7 +1195,6 @@ WRAP_API(bool, lxcapi_stop)
 
 static int do_create_container_dir(const char *path, struct lxc_conf *conf)
 {
-       __do_free char *p = NULL;
        int lasterr;
        int ret = -1;
 
@@ -1216,10 +1210,8 @@ static int do_create_container_dir(const char *path, struct lxc_conf *conf)
                ret = 0;
        }
 
-       p = must_copy_string(path);
-
        if (!lxc_list_empty(&conf->id_map)) {
-               ret = chown_mapped_root(p, conf);
+               ret = chown_mapped_root(path, conf);
                if (ret < 0)
                        ret = -1;
        }
@@ -1279,7 +1271,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
        if (ret < 0 || (size_t)ret >= len)
                return NULL;
 
-       bdev = storage_create(dest, type, c->name, specs);
+       bdev = storage_create(dest, type, c->name, specs, c->lxc_conf);
        if (!bdev) {
                ERROR("Failed to create \"%s\" storage", type);
                return NULL;
@@ -1294,8 +1286,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
        /* If we are not root, chown the rootfs dir to root in the target user
         * namespace.
         */
-       ret = geteuid();
-       if (ret != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) {
+       if (am_guest_unpriv() || !lxc_list_empty(&c->lxc_conf->id_map)) {
                ret = chown_mapped_root(bdev->dest, c->lxc_conf);
                if (ret < 0) {
                        ERROR("Error chowning \"%s\" to container root", bdev->dest);
@@ -1364,14 +1355,8 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
                                _exit(EXIT_FAILURE);
                        }
 
-                       ret = detect_shared_rootfs();
-                       if (ret == 1) {
-                               ret = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL);
-                               if (ret < 0) {
-                                       SYSERROR("Failed to make \"/\" rslave");
-                                       ERROR("Continuing...");
-                               }
-                       }
+                       if (detect_shared_rootfs() && mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL))
+                               SYSERROR("Failed to recursively turn root mount tree into dependent mount. Continuing...");
                }
 
                if (strcmp(bdev->type, "dir") != 0 && strcmp(bdev->type, "btrfs") != 0) {
@@ -1649,7 +1634,7 @@ static bool prepend_lxc_header(char *path, const char *t, char *const argv[])
        char *tpath;
 #endif
 
-       f = fopen(path, "r");
+       f = fopen(path, "re");
        if (f == NULL)
                return false;
 
@@ -1702,7 +1687,7 @@ static bool prepend_lxc_header(char *path, const char *t, char *const argv[])
        free(tpath);
 #endif
 
-       f = fopen(path, "w");
+       f = fopen(path, "we");
        if (f == NULL) {
                SYSERROR("Reopening config for writing");
                free(contents);
@@ -1967,8 +1952,9 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 
 static bool do_lxcapi_reboot(struct lxc_container *c)
 {
+       __do_close int pidfd = -EBADF;
+       pid_t pid = -1;
        int ret;
-       pid_t pid;
        int rebootsignal = SIGINT;
 
        if (!c)
@@ -1977,18 +1963,23 @@ static bool do_lxcapi_reboot(struct lxc_container *c)
        if (!do_lxcapi_is_running(c))
                return false;
 
-       pid = do_lxcapi_init_pid(c);
-       if (pid <= 0)
-               return false;
+       pidfd = do_lxcapi_init_pidfd(c);
+       if (pidfd < 0) {
+               pid = do_lxcapi_init_pid(c);
+               if (pid <= 0)
+                       return false;
+       }
 
        if (c->lxc_conf && c->lxc_conf->rebootsignal)
                rebootsignal = c->lxc_conf->rebootsignal;
 
-       ret = kill(pid, rebootsignal);
-       if (ret < 0) {
-               WARN("Failed to send signal %d to pid %d", rebootsignal, pid);
-               return false;
-       }
+       if (pidfd >= 0)
+               ret = lxc_raw_pidfd_send_signal(pidfd, rebootsignal, NULL, 0);
+       else
+               ret = kill(pid, rebootsignal);
+       if (ret < 0)
+               return log_warn(false, "Failed to send signal %d to pid %d",
+                               rebootsignal, pid);
 
        return true;
 }
@@ -1997,10 +1988,11 @@ WRAP_API(bool, lxcapi_reboot)
 
 static bool do_lxcapi_reboot2(struct lxc_container *c, int timeout)
 {
-       int killret, ret;
-       pid_t pid;
-       int rebootsignal = SIGINT, state_client_fd = -1;
+       __do_close int pidfd = -EBADF, state_client_fd = -EBADF;
+       int rebootsignal = SIGINT;
+       pid_t pid = -1;
        lxc_state_t states[MAX_STATE] = {0};
+       int killret, ret;
 
        if (!c)
                return false;
@@ -2008,9 +2000,12 @@ static bool do_lxcapi_reboot2(struct lxc_container *c, int timeout)
        if (!do_lxcapi_is_running(c))
                return true;
 
-       pid = do_lxcapi_init_pid(c);
-       if (pid <= 0)
-               return true;
+       pidfd = do_lxcapi_init_pidfd(c);
+       if (pidfd < 0) {
+               pid = do_lxcapi_init_pid(c);
+               if (pid <= 0)
+                       return true;
+       }
 
        if (c->lxc_conf && c->lxc_conf->rebootsignal)
                rebootsignal = c->lxc_conf->rebootsignal;
@@ -2036,21 +2031,18 @@ static bool do_lxcapi_reboot2(struct lxc_container *c, int timeout)
        }
 
        /* Send reboot signal to container. */
-       killret = kill(pid, rebootsignal);
-       if (killret < 0) {
-               if (state_client_fd >= 0)
-                       close(state_client_fd);
-
-               WARN("Failed to send signal %d to pid %d", rebootsignal, pid);
-               return false;
-       }
+       if (pidfd >= 0)
+               killret = lxc_raw_pidfd_send_signal(pidfd, rebootsignal, NULL, 0);
+       else
+               killret = kill(pid, rebootsignal);
+       if (killret < 0)
+               return log_warn(false, "Failed to send signal %d to pid %d", rebootsignal, pid);
        TRACE("Sent signal %d to pid %d", rebootsignal, pid);
 
        if (timeout == 0)
                return true;
 
        ret = lxc_cmd_sock_rcv_state(state_client_fd, timeout);
-       close(state_client_fd);
        if (ret < 0)
                return false;
 
@@ -2065,10 +2057,11 @@ WRAP_API_1(bool, lxcapi_reboot2, int)
 
 static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 {
-       int killret, ret;
-       pid_t pid;
-       int haltsignal = SIGPWR, state_client_fd = -EBADF;
+       __do_close int pidfd = -EBADF, state_client_fd = -EBADF;
+       int haltsignal = SIGPWR;
+       pid_t pid = -1;
        lxc_state_t states[MAX_STATE] = {0};
+       int killret, ret;
 
        if (!c)
                return false;
@@ -2076,6 +2069,7 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
        if (!do_lxcapi_is_running(c))
                return true;
 
+       pidfd = do_lxcapi_init_pidfd(c);
        pid = do_lxcapi_init_pid(c);
        if (pid <= 0)
                return true;
@@ -2086,8 +2080,10 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
        else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
                haltsignal = (SIGRTMIN + 3);
 
-       /* Add a new state client before sending the shutdown signal so that we
-        * don't miss a state.
+
+       /*
+        * Add a new state client before sending the shutdown signal so
+        * that we don't miss a state.
         */
        if (timeout != 0) {
                states[STOPPED] = 1;
@@ -2106,22 +2102,45 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
                        return false;
        }
 
-       /* Send shutdown signal to container. */
-       killret = kill(pid, haltsignal);
-       if (killret < 0) {
-               if (state_client_fd >= 0)
-                       close(state_client_fd);
+       if (pidfd >= 0) {
+               struct pollfd pidfd_poll = {
+                   .events = POLLIN,
+                   .fd = pidfd,
+               };
 
-               WARN("Failed to send signal %d to pid %d", haltsignal, pid);
-               return false;
+               killret = lxc_raw_pidfd_send_signal(pidfd, haltsignal,
+                                                   NULL, 0);
+               if (killret < 0)
+                       return log_warn(false, "Failed to send signal %d to pidfd %d",
+                                       haltsignal, pidfd);
+
+               TRACE("Sent signal %d to pidfd %d", haltsignal, pidfd);
+
+               /*
+                * No need for going through all of the state server
+                * complications anymore. We can just poll on pidfds. :)
+                */
+
+               if (timeout != 0) {
+                       ret = poll(&pidfd_poll, 1, timeout * 1000);
+                       if (ret < 0 || !(pidfd_poll.revents & POLLIN))
+                               return false;
+
+                       TRACE("Pidfd polling detected container exit");
+               }
+       } else {
+               killret = kill(pid, haltsignal);
+               if (killret < 0)
+                       return log_warn(false, "Failed to send signal %d to pid %d",
+                                       haltsignal, pid);
+
+               TRACE("Sent signal %d to pid %d", haltsignal, pid);
        }
-       TRACE("Sent signal %d to pid %d", haltsignal, pid);
 
        if (timeout == 0)
                return true;
 
        ret = lxc_cmd_sock_rcv_state(state_client_fd, timeout);
-       close(state_client_fd);
        if (ret < 0)
                return false;
 
@@ -2321,20 +2340,21 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
        char **interfaces = NULL;
        char interface[IFNAMSIZ];
 
-       if (pipe2(pipefd, O_CLOEXEC) < 0)
-               return NULL;
+       if (pipe2(pipefd, O_CLOEXEC))
+               return log_error_errno(NULL, errno, "Failed to create pipe");
 
        pid = fork();
        if (pid < 0) {
-               SYSERROR("Failed to fork task to get interfaces information");
                close(pipefd[0]);
                close(pipefd[1]);
-               return NULL;
+               return log_error_errno(NULL, errno, "Failed to fork task to get interfaces information");
        }
 
-       if (pid == 0) { /* child */
-               int ret = 1, nbytes;
-               struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+       if (pid == 0) {
+               call_cleaner(netns_freeifaddrs) struct netns_ifaddrs *ifaddrs = NULL;
+               struct netns_ifaddrs *ifa = NULL;
+               int ret = 1;
+               int nbytes;
 
                /* close the read-end of the pipe */
                close(pipefd[0]);
@@ -2345,15 +2365,15 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
                }
 
                /* Grab the list of interfaces */
-               if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
+               if (netns_getifaddrs(&ifaddrs, -1, &(bool){false})) {
                        SYSERROR("Failed to get interfaces list");
                        goto out;
                }
 
                /* Iterate through the interfaces */
-               for (tempIfAddr = interfaceArray; tempIfAddr != NULL;
-                    tempIfAddr = tempIfAddr->ifa_next) {
-                       nbytes = lxc_write_nointr(pipefd[1], tempIfAddr->ifa_name, IFNAMSIZ);
+               for (ifa = ifaddrs; ifa != NULL;
+                    ifa = ifa->ifa_next) {
+                       nbytes = lxc_write_nointr(pipefd[1], ifa->ifa_name, IFNAMSIZ);
                        if (nbytes < 0)
                                goto out;
 
@@ -2363,9 +2383,6 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
                ret = 0;
 
        out:
-               if (interfaceArray)
-                       netns_freeifaddrs(interfaceArray);
-
                /* close the write-end of the pipe, thus sending EOF to the reader */
                close(pipefd[1]);
                _exit(ret);
@@ -2386,7 +2403,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
                count++;
        }
 
-       if (wait_for_pid(pid) != 0) {
+       if (wait_for_pid(pid)) {
                for (i = 0; i < count; i++)
                        free(interfaces[i]);
 
@@ -2417,10 +2434,8 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
        char **addresses = NULL;
 
        ret = pipe2(pipefd, O_CLOEXEC);
-       if (ret < 0) {
-               SYSERROR("Failed to create pipe");
-               return NULL;
-       }
+       if (ret < 0)
+               return log_error_errno(NULL, errno, "Failed to create pipe");
 
        pid = fork();
        if (pid < 0) {
@@ -2431,11 +2446,12 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
        }
 
        if (pid == 0) {
+               call_cleaner(netns_freeifaddrs) struct netns_ifaddrs *ifaddrs = NULL;
+               struct netns_ifaddrs *ifa = NULL;
                ssize_t nbytes;
                char addressOutputBuffer[INET6_ADDRSTRLEN];
                char *address_ptr = NULL;
-               void *tempAddrPtr = NULL;
-               struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+               void *address_ptr_tmp = NULL;
 
                /* close the read-end of the pipe */
                close(pipefd[0]);
@@ -2446,52 +2462,50 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
                }
 
                /* Grab the list of interfaces */
-               if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
+               if (netns_getifaddrs(&ifaddrs, -1, &(bool){false})) {
                        SYSERROR("Failed to get interfaces list");
                        goto out;
                }
 
                /* Iterate through the interfaces */
-               for (tempIfAddr = interfaceArray; tempIfAddr;
-                    tempIfAddr = tempIfAddr->ifa_next) {
-                       if (tempIfAddr->ifa_addr == NULL)
+               for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+                       if (ifa->ifa_addr == NULL)
                                continue;
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-align"
 
-                       if (tempIfAddr->ifa_addr->sa_family == AF_INET) {
+                       if (ifa->ifa_addr->sa_family == AF_INET) {
                                if (family && strcmp(family, "inet"))
                                        continue;
 
-                               tempAddrPtr = &((struct sockaddr_in *)tempIfAddr->ifa_addr)->sin_addr;
+                               address_ptr_tmp = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
                        } else {
                                if (family && strcmp(family, "inet6"))
                                        continue;
 
-                               if (((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_scope_id != scope)
+                               if (((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id != scope)
                                        continue;
 
-                               tempAddrPtr = &((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_addr;
+                               address_ptr_tmp = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
                        }
 
 #pragma GCC diagnostic pop
 
-                       if (interface && strcmp(interface, tempIfAddr->ifa_name))
+                       if (interface && strcmp(interface, ifa->ifa_name))
                                continue;
-                       else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0)
+                       else if (!interface && strcmp("lo", ifa->ifa_name) == 0)
                                continue;
 
-                       address_ptr = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family,
-                                                   tempAddrPtr, addressOutputBuffer,
-                                                   sizeof(addressOutputBuffer));
+                       address_ptr = (char *)inet_ntop(ifa->ifa_addr->sa_family, address_ptr_tmp,
+                                                       addressOutputBuffer,
+                                                       sizeof(addressOutputBuffer));
                        if (!address_ptr)
                                continue;
 
                        nbytes = lxc_write_nointr(pipefd[1], address_ptr, INET6_ADDRSTRLEN);
                        if (nbytes != INET6_ADDRSTRLEN) {
-                               SYSERROR("Failed to send ipv6 address \"%s\"",
-                                        address_ptr);
+                               SYSERROR("Failed to send ipv6 address \"%s\"", address_ptr);
                                goto out;
                        }
 
@@ -2501,9 +2515,6 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
                ret = 0;
 
        out:
-               if (interfaceArray)
-                       netns_freeifaddrs(interfaceArray);
-
                /* close the write-end of the pipe, thus sending EOF to the reader */
                close(pipefd[1]);
                _exit(ret);
@@ -2521,7 +2532,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
                count++;
        }
 
-       if (wait_for_pid(pid) != 0) {
+       if (wait_for_pid(pid)) {
                for (i = 0; i < count; i++)
                        free(addresses[i]);
 
@@ -2699,7 +2710,7 @@ static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc
 
        /* If we find an lxc-snapshot file using the old format only listing the
         * number of snapshots we will keep using it. */
-       f1 = fopen(path, "r");
+       f1 = fopen(path, "re");
        if (f1) {
                n = fscanf(f1, "%d", &v);
                fclose(f1);
@@ -2714,7 +2725,7 @@ static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc
 
        if (n == 1) {
                v += inc ? 1 : -1;
-               f1 = fopen(path, "w");
+               f1 = fopen(path, "we");
                if (!f1)
                        goto out;
 
@@ -2733,7 +2744,7 @@ static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc
                /* Here we know that we have or can use an lxc-snapshot file
                 * using the new format. */
                if (inc) {
-                       f1 = fopen(path, "a");
+                       f1 = fopen(path, "ae");
                        if (!f1)
                                goto out;
 
@@ -2804,10 +2815,11 @@ out:
 
 void mod_all_rdeps(struct lxc_container *c, bool inc)
 {
-       struct lxc_container *p;
-       char *lxcpath = NULL, *lxcname = NULL, path[PATH_MAX];
+       __do_free char *lxcpath = NULL, *lxcname = NULL;
+       __do_fclose FILE *f = NULL;
        size_t pathlen = 0, namelen = 0;
-       FILE *f;
+       struct lxc_container *p;
+       char path[PATH_MAX];
        int ret;
 
        ret = snprintf(path, PATH_MAX, "%s/%s/lxc_rdepends",
@@ -2817,14 +2829,14 @@ void mod_all_rdeps(struct lxc_container *c, bool inc)
                return;
        }
 
-       f = fopen(path, "r");
-       if (f == NULL)
+       f = fopen(path, "re");
+       if (!f)
                return;
 
        while (getline(&lxcpath, &pathlen, f) != -1) {
                if (getline(&lxcname, &namelen, f) == -1) {
                        ERROR("badly formatted file %s", path);
-                       goto out;
+                       return;
                }
 
                remove_trailing_newlines(lxcpath);
@@ -2842,55 +2854,44 @@ void mod_all_rdeps(struct lxc_container *c, bool inc)
 
                lxc_container_put(p);
        }
-
-out:
-       free(lxcpath);
-       free(lxcname);
-       fclose(f);
 }
 
 static bool has_fs_snapshots(struct lxc_container *c)
 {
-       FILE *f;
+       __do_fclose FILE *f = NULL;
        char path[PATH_MAX];
        int ret, v;
        struct stat fbuf;
-       bool bret = false;
 
        ret = snprintf(path, PATH_MAX, "%s/%s/lxc_snapshots", c->config_path,
                        c->name);
        if (ret < 0 || ret > PATH_MAX)
-               goto out;
+               return false;
 
        /* If the file doesn't exist there are no snapshots. */
        if (stat(path, &fbuf) < 0)
-               goto out;
+               return false;
 
        v = fbuf.st_size;
        if (v != 0) {
-               f = fopen(path, "r");
+               f = fopen(path, "re");
                if (!f)
-                       goto out;
+                       return false;
 
                ret = fscanf(f, "%d", &v);
-               fclose(f);
-               /* TODO: Figure out what to do with the return value of fscanf. */
                if (ret != 1)
                        INFO("Container uses new lxc-snapshots format %s", path);
        }
 
-       bret = v != 0;
-
-out:
-       return bret;
+       return v != 0;
 }
 
 static bool has_snapshots(struct lxc_container *c)
 {
+       __do_closedir DIR *dir = NULL;
        char path[PATH_MAX];
        struct dirent *direntp;
-       int count=0;
-       DIR *dir;
+       int count = 0;
 
        if (!get_snappath_dir(c, path))
                return false;
@@ -2909,7 +2910,6 @@ static bool has_snapshots(struct lxc_container *c)
                break;
        }
 
-       closedir(dir);
        return count > 0;
 }
 
@@ -3276,8 +3276,7 @@ WRAP_API_1(bool, lxcapi_set_config_path, const char *)
 
 static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
 {
-       int ret;
-       struct cgroup_ops *cgroup_ops;
+       call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
 
        if (!c)
                return false;
@@ -3289,19 +3288,15 @@ static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsy
        if (!cgroup_ops)
                return false;
 
-       ret = cgroup_ops->set(cgroup_ops, subsys, value, c->name, c->config_path);
-
-       cgroup_exit(cgroup_ops);
-
-       return ret == 0;
+       return cgroup_ops->set(cgroup_ops, subsys, value, c->name,
+                              c->config_path) == 0;
 }
 
 WRAP_API_2(bool, lxcapi_set_cgroup_item, const char *, const char *)
 
 static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
 {
-       int ret;
-       struct cgroup_ops *cgroup_ops;
+       call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
 
        if (!c)
                return -1;
@@ -3313,12 +3308,8 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys
        if (!cgroup_ops)
                return -1;
 
-       ret = cgroup_ops->get(cgroup_ops, subsys, retv, inlen, c->name,
-                             c->config_path);
-
-       cgroup_exit(cgroup_ops);
-
-       return ret;
+       return cgroup_ops->get(cgroup_ops, subsys, retv, inlen, c->name,
+                              c->config_path);
 }
 
 WRAP_API_3(int, lxcapi_get_cgroup_item, const char *, char *, int)
@@ -3530,30 +3521,20 @@ static void copy_rdepends(struct lxc_container *c, struct lxc_container *c0)
 
 static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0)
 {
+       __do_fclose FILE *f = NULL;
        int ret;
        char path[PATH_MAX];
-       FILE *f;
-       bool bret;
 
-       ret = snprintf(path, PATH_MAX, "%s/%s/lxc_rdepends", c->config_path,
-               c->name);
-       if (ret < 0 || ret >= PATH_MAX)
+       ret = snprintf(path, sizeof(path), "%s/%s/lxc_rdepends", c->config_path, c->name);
+       if (ret < 0 || ret >= sizeof(path))
                return false;
 
-       f = fopen(path, "a");
+       f = fopen(path, "ae");
        if (!f)
                return false;
 
-       bret = true;
-
        /* If anything goes wrong, just return an error. */
-       if (fprintf(f, "%s\n%s\n", c0->config_path, c0->name) < 0)
-               bret = false;
-
-       if (fclose(f) != 0)
-               bret = false;
-
-       return bret;
+       return fprintf(f, "%s\n%s\n", c0->config_path, c0->name) > 0;
 }
 
 /*
@@ -3561,7 +3542,7 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0)
  * then default to those even if not requested.
  * Currently we only do this for btrfs.
  */
-bool should_default_to_snapshot(struct lxc_container *c0,
+static bool should_default_to_snapshot(struct lxc_container *c0,
                                struct lxc_container *c1)
 {
        __do_free char *p0 = NULL, *p1 = NULL;
@@ -3686,12 +3667,8 @@ static int clone_update_rootfs(struct clone_update_data *data)
                        return -1;
                }
 
-               if (detect_shared_rootfs()) {
-                       if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
-                               SYSERROR("Failed to make / rslave");
-                               ERROR("Continuing...");
-                       }
-               }
+               if (detect_shared_rootfs() && mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL))
+                       SYSERROR("Failed to recursively turn root mount tree into dependent mount. Continuing...");
 
                if (bdev->ops->mount(bdev) < 0) {
                        storage_put(bdev);
@@ -3736,7 +3713,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
                if (!file_exists(path))
                        return 0;
 
-               if (!(fout = fopen(path, "w"))) {
+               if (!(fout = fopen(path, "we"))) {
                        SYSERROR("unable to open %s: ignoring", path);
                        return 0;
                }
@@ -4216,7 +4193,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
        len = strlen(snappath) + 1 + strlen(newname) + 1 + strlen(LXC_TIMESTAMP_FNAME) + 1;
        dfnam = must_realloc(NULL, len);
        snprintf(dfnam, len, "%s/%s/%s", snappath, newname, LXC_TIMESTAMP_FNAME);
-       f = fopen(dfnam, "w");
+       f = fopen(dfnam, "we");
        if (!f) {
                ERROR("Failed to open %s", dfnam);
                return -1;
@@ -4276,15 +4253,16 @@ static char *get_snapcomment_path(char* snappath, char *name)
 
 static char *get_timestamp(char* snappath, char *name)
 {
-       char path[PATH_MAX], *s = NULL;
+       __do_free char *s = NULL;
+       __do_fclose FILE *fin = NULL;
+       char path[PATH_MAX];
        int ret, len;
-       FILE *fin;
 
        ret = snprintf(path, PATH_MAX, "%s/%s/ts", snappath, name);
        if (ret < 0 || ret >= PATH_MAX)
                return NULL;
 
-       fin = fopen(path, "r");
+       fin = fopen(path, "re");
        if (!fin)
                return NULL;
 
@@ -4295,25 +4273,21 @@ static char *get_timestamp(char* snappath, char *name)
                s = malloc(len+1);
                if (s) {
                        s[len] = '\0';
-                       if (fread(s, 1, len, fin) != len) {
-                               SYSERROR("reading timestamp");
-                               free(s);
-                               s = NULL;
-                       }
+                       if (fread(s, 1, len, fin) != len)
+                               return log_error_errno(NULL, errno, "reading timestamp");
                }
        }
 
-       fclose(fin);
-       return s;
+       return move_ptr(s);
 }
 
 static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps)
 {
+       __do_closedir DIR *dir = NULL;
        char snappath[PATH_MAX], path2[PATH_MAX];
        int count = 0, ret;
        struct dirent *direntp;
        struct lxc_snapshot *snaps =NULL, *nsnaps;
-       DIR *dir;
 
        if (!c || !lxcapi_is_defined(c))
                return -1;
@@ -4368,25 +4342,17 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
                count++;
        }
 
-       if (closedir(dir))
-               WARN("Failed to close directory");
-
        *ret_snaps = snaps;
        return count;
 
 out_free:
        if (snaps) {
-               int i;
-
-               for (i=0; i<count; i++)
+               for (int i = 0; i < count; i++)
                        lxcsnap_free(&snaps[i]);
 
                free(snaps);
        }
 
-       if (closedir(dir))
-               WARN("Failed to close directory");
-
        return -1;
 }
 
@@ -4499,7 +4465,7 @@ err:
 
 static bool remove_all_snapshots(const char *path)
 {
-       DIR *dir;
+       __do_closedir DIR *dir = NULL;
        struct dirent *direntp;
        bool bret = true;
 
@@ -4522,8 +4488,6 @@ static bool remove_all_snapshots(const char *path)
                }
        }
 
-       closedir(dir);
-
        if (rmdir(path))
                SYSERROR("Error removing directory %s", path);
 
@@ -5268,6 +5232,16 @@ static int do_lxcapi_seccomp_notify_fd(struct lxc_container *c)
 
 WRAP_API(int, lxcapi_seccomp_notify_fd)
 
+static int do_lxcapi_seccomp_notify_fd_active(struct lxc_container *c)
+{
+       if (!c || !c->lxc_conf)
+               return ret_set_errno(-1, -EINVAL);
+
+       return lxc_cmd_get_seccomp_notify_fd(c->name, c->config_path);
+}
+
+WRAP_API(int, lxcapi_seccomp_notify_fd_active)
+
 struct lxc_container *lxc_container_new(const char *name, const char *configpath)
 {
        struct lxc_container *c;
@@ -5357,7 +5331,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
        c->unfreeze = lxcapi_unfreeze;
        c->console = lxcapi_console;
        c->console_getfd = lxcapi_console_getfd;
+       c->devpts_fd = lxcapi_devpts_fd;
        c->init_pid = lxcapi_init_pid;
+       c->init_pidfd = lxcapi_init_pidfd;
        c->load_config = lxcapi_load_config;
        c->want_daemonize = lxcapi_want_daemonize;
        c->want_close_all_fds = lxcapi_want_close_all_fds;
@@ -5408,6 +5384,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
        c->mount = lxcapi_mount;
        c->umount = lxcapi_umount;
        c->seccomp_notify_fd = lxcapi_seccomp_notify_fd;
+       c->seccomp_notify_fd_active = lxcapi_seccomp_notify_fd_active;
 
        return c;
 
@@ -5433,7 +5410,7 @@ int lxc_get_wait_states(const char **states)
  */
 int list_defined_containers(const char *lxcpath, char ***names, struct lxc_container ***cret)
 {
-       DIR *dir;
+       __do_closedir DIR *dir = NULL;
        int i, cfound = 0, nfound = 0;
        struct dirent *direntp;
        struct lxc_container *c;
@@ -5504,32 +5481,31 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
                nfound++;
        }
 
-       closedir(dir);
        return nfound;
 
 free_bad:
        if (names && *names) {
-               for (i=0; i<cfound; i++)
+               for (i = 0; i < cfound; i++)
                        free((*names)[i]);
                free(*names);
        }
 
        if (cret && *cret) {
-               for (i=0; i<nfound; i++)
+               for (i = 0; i < nfound; i++)
                        lxc_container_put((*cret)[i]);
                free(*cret);
        }
 
-       closedir(dir);
        return -1;
 }
 
 int list_active_containers(const char *lxcpath, char ***nret,
                           struct lxc_container ***cret)
 {
+       __do_free char *line = NULL;
+       __do_fclose FILE *f = NULL;
        int i, ret = -1, cret_cnt = 0, ct_name_cnt = 0;
        int lxcpath_len;
-       char *line = NULL;
        char **ct_name = NULL;
        size_t len = 0;
        struct lxc_container *c = NULL;
@@ -5545,7 +5521,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
        if (nret)
                *nret = NULL;
 
-       FILE *f = fopen("/proc/net/unix", "r");
+       f = fopen("/proc/net/unix", "re");
        if (!f)
                return -1;
 
@@ -5673,8 +5649,6 @@ free_ct_name:
        }
 
 out:
-       free(line);
-       fclose(f);
        return ret;
 }
 
@@ -5767,7 +5741,7 @@ free_ct_name:
 
 bool lxc_config_item_is_supported(const char *key)
 {
-       return !!lxc_get_config(key);
+       return !!lxc_get_config_exact(key);
 }
 
 bool lxc_has_api_extension(const char *extension)