]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/conf.c
conf: cleanup macros suggest_default_idmap
[mirror_lxc.git] / src / lxc / conf.c
index 997588a9e839d3224350098fe97d639dd0bb609c..c0ac73be2a97ab10d23a228f2dce0fb0985acaf2 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define _GNU_SOURCE
-#include "config.h"
-#include "confile.h"
-
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
 #include <arpa/inet.h>
 #include <dirent.h>
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
 
+#include "af_unix.h"
+#include "caps.h"
+#include "cgroup.h"
+#include "conf.h"
+#include "config.h"
+#include "confile.h"
+#include "confile_utils.h"
+#include "error.h"
+#include "log.h"
+#include "lsm/lsm.h"
+#include "lxclock.h"
+#include "lxcseccomp.h"
+#include "macro.h"
+#include "memory_utils.h"
+#include "namespace.h"
+#include "network.h"
+#include "parse.h"
+#include "raw_syscalls.h"
+#include "ringbuf.h"
+#include "start.h"
+#include "storage.h"
+#include "storage/overlay.h"
+#include "syscall_wrappers.h"
+#include "terminal.h"
+#include "utils.h"
+
 #ifdef MAJOR_IN_MKDEV
 #include <sys/mkdev.h>
 #endif
 #include <../include/prlimit.h>
 #endif
 
-#include "af_unix.h"
-#include "caps.h"
-#include "cgroup.h"
-#include "conf.h"
-#include "confile_utils.h"
-#include "error.h"
-#include "log.h"
-#include "lsm/lsm.h"
-#include "lxclock.h"
-#include "lxcseccomp.h"
-#include "macro.h"
-#include "namespace.h"
-#include "network.h"
-#include "parse.h"
-#include "ringbuf.h"
-#include "start.h"
-#include "storage.h"
-#include "storage/overlay.h"
-#include "terminal.h"
-#include "utils.h"
-
 lxc_log_define(conf, lxc);
 
 /* The lxc_conf of the container currently being worked on in an API call.
@@ -123,21 +127,6 @@ thread_local struct lxc_conf *current_config;
 struct lxc_conf *current_config;
 #endif
 
-/* Define pivot_root() if missing from the C library */
-#ifndef HAVE_PIVOT_ROOT
-static int pivot_root(const char *new_root, const char *put_old)
-{
-#ifdef __NR_pivot_root
-       return syscall(__NR_pivot_root, new_root, put_old);
-#else
-       errno = ENOSYS;
-       return -1;
-#endif
-}
-#else
-extern int pivot_root(const char *new_root, const char *put_old);
-#endif
-
 char *lxchook_names[NUM_LXC_HOOKS] = {
        "pre-start",
        "pre-mount",
@@ -317,8 +306,8 @@ static struct limit_opt limit_opt[] = {
 
 static int run_buffer(char *buffer)
 {
+       __do_free char *output = NULL;
        int ret;
-       char *output;
        struct lxc_popen_FILE *f;
 
        f = lxc_popen(buffer);
@@ -337,8 +326,6 @@ static int run_buffer(char *buffer)
        while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
                DEBUG("Script %s with output: %s", buffer, output);
 
-       free(output);
-
        ret = lxc_pclose(f);
        if (ret == -1) {
                SYSERROR("Script exited with error");
@@ -358,9 +345,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
                    const char *section, const char *script,
                    const char *hookname, char **argv)
 {
+       __do_free char *buffer = NULL;
        int buf_pos, i, ret;
-       char *buffer;
-       int fret = -1;
        size_t size = 0;
 
        if (hook_version == 0)
@@ -372,7 +358,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
        for (i = 0; argv && argv[i]; i++)
                size += strlen(argv[i]) + 1;
 
-       size += sizeof("exec");
+       size += STRLITERALLEN("exec");
+       size++;
        size += strlen(script);
        size++;
 
@@ -403,7 +390,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                buf_pos = snprintf(buffer, size, "exec %s", script);
        if (buf_pos < 0 || (size_t)buf_pos >= size) {
                ERROR("Failed to create command line for script \"%s\"", script);
-               goto on_error;
+               return -1;
        }
 
        if (hook_version == 1) {
@@ -411,7 +398,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                if (ret < 0) {
                        SYSERROR("Failed to set environment variable: "
                                 "LXC_HOOK_TYPE=%s", hookname);
-                       goto on_error;
+                       return -1;
                }
                TRACE("Set environment variable: LXC_HOOK_TYPE=%s", hookname);
 
@@ -419,7 +406,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                if (ret < 0) {
                        SYSERROR("Failed to set environment variable: "
                                 "LXC_HOOK_SECTION=%s", section);
-                       goto on_error;
+                       return -1;
                }
                TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
 
@@ -427,13 +414,13 @@ int run_script_argv(const char *name, unsigned int hook_version,
                        char *parent;
 
                        if (!argv || !argv[0])
-                               goto on_error;
+                               return -1;
 
                        ret = setenv("LXC_NET_TYPE", argv[0], 1);
                        if (ret < 0) {
                                SYSERROR("Failed to set environment variable: "
                                         "LXC_NET_TYPE=%s", argv[0]);
-                               goto on_error;
+                               return -1;
                        }
                        TRACE("Set environment variable: LXC_NET_TYPE=%s", argv[0]);
 
@@ -444,7 +431,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                                if (ret < 0) {
                                        SYSERROR("Failed to set environment "
                                                 "variable: LXC_NET_PARENT=%s", parent);
-                                       goto on_error;
+                                       return -1;
                                }
                                TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
                        } else if (strcmp(argv[0], "phys") == 0) {
@@ -452,7 +439,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                                if (ret < 0) {
                                        SYSERROR("Failed to set environment "
                                                 "variable: LXC_NET_PARENT=%s", parent);
-                                       goto on_error;
+                                       return -1;
                                }
                                TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
                        } else if (strcmp(argv[0], "veth") == 0) {
@@ -462,7 +449,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                                if (ret < 0) {
                                        SYSERROR("Failed to set environment "
                                                 "variable: LXC_NET_PEER=%s", peer);
-                                       goto on_error;
+                                       return -1;
                                }
                                TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
 
@@ -470,7 +457,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
                                if (ret < 0) {
                                        SYSERROR("Failed to set environment "
                                                 "variable: LXC_NET_PARENT=%s", parent);
-                                       goto on_error;
+                                       return -1;
                                }
                                TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
                        }
@@ -483,22 +470,19 @@ int run_script_argv(const char *name, unsigned int hook_version,
                ret = snprintf(buffer + buf_pos, len, " %s", argv[i]);
                if (ret < 0 || (size_t)ret >= len) {
                        ERROR("Failed to create command line for script \"%s\"", script);
-                       goto on_error;
+                       return -1;
                }
                buf_pos += ret;
        }
 
-       fret = run_buffer(buffer);
-
-on_error:
-       free(buffer);
-       return fret;
+       return run_buffer(buffer);
 }
 
 int run_script(const char *name, const char *section, const char *script, ...)
 {
+       __do_free char *buffer = NULL;
        int ret;
-       char *buffer, *p;
+       char *p;
        va_list ap;
        size_t size = 0;
 
@@ -510,7 +494,7 @@ int run_script(const char *name, const char *section, const char *script, ...)
                size += strlen(p) + 1;
        va_end(ap);
 
-       size += strlen("exec");
+       size += STRLITERALLEN("exec");
        size += strlen(script);
        size += strlen(name);
        size += strlen(section);
@@ -519,7 +503,7 @@ int run_script(const char *name, const char *section, const char *script, ...)
        if (size > INT_MAX)
                return -1;
 
-       buffer = alloca(size);
+       buffer = must_realloc(NULL, size);
        ret = snprintf(buffer, size, "exec %s %s %s", script, name, section);
        if (ret < 0 || ret >= size)
                return -1;
@@ -552,15 +536,17 @@ int run_script(const char *name, const char *section, const char *script, ...)
  */
 int pin_rootfs(const char *rootfs)
 {
+       __do_free char *absrootfs = NULL;
        int fd, ret;
-       char absrootfs[MAXPATHLEN], absrootfspin[MAXPATHLEN];
+       char absrootfspin[PATH_MAX];
        struct stat s;
        struct statfs sfs;
 
        if (rootfs == NULL || strlen(rootfs) == 0)
                return -2;
 
-       if (!realpath(rootfs, absrootfs))
+       absrootfs = realpath(rootfs, NULL);
+       if (!absrootfs)
                return -2;
 
        ret = stat(absrootfs, &s);
@@ -570,8 +556,8 @@ int pin_rootfs(const char *rootfs)
        if (!S_ISDIR(s.st_mode))
                return -2;
 
-       ret = snprintf(absrootfspin, MAXPATHLEN, "%s/.lxc-keep", absrootfs);
-       if (ret >= MAXPATHLEN)
+       ret = snprintf(absrootfspin, PATH_MAX, "%s/.lxc-keep", absrootfs);
+       if (ret < 0 || ret >= PATH_MAX)
                return -1;
 
        fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
@@ -643,7 +629,7 @@ unsigned long add_required_remount_flags(const char *s, const char *d,
 
 static int add_shmount_to_list(struct lxc_conf *conf)
 {
-       char new_mount[MAXPATHLEN];
+       char new_mount[PATH_MAX];
        /* Offset for the leading '/' since the path_cont
         * is absolute inside the container.
         */
@@ -694,6 +680,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_RW,     "sysfs",                                          "%r/sys",                     "sysfs", 0,                                               NULL },
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_RO,     "sysfs",                                          "%r/sys",                     "sysfs", MS_RDONLY,                                       NULL },
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_MIXED,  "sysfs",                                          "%r/sys",                     "sysfs", MS_NODEV|MS_NOEXEC|MS_NOSUID,                    NULL },
+               { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_MIXED,  "%r/sys",                                         "%r/sys",                     NULL,    MS_BIND,                                         NULL },
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_MIXED,  NULL,                                             "%r/sys",                     NULL,    MS_REMOUNT|MS_BIND|MS_RDONLY,                    NULL },
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_MIXED,  "sysfs",                                          "%r/sys/devices/virtual/net", "sysfs", 0,                                               NULL },
                { LXC_AUTO_SYS_MASK,  LXC_AUTO_SYS_MIXED,  "%r/sys/devices/virtual/net/devices/virtual/net", "%r/sys/devices/virtual/net", NULL,    MS_BIND,                                         NULL },
@@ -702,10 +689,9 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
        };
 
        for (i = 0; default_mounts[i].match_mask; i++) {
+               __do_free char *destination = NULL, *source = NULL;
                int saved_errno;
                unsigned long mflags;
-               char *destination = NULL;
-               char *source = NULL;
                if ((flags & default_mounts[i].match_mask) != default_mounts[i].match_flag)
                        continue;
 
@@ -718,16 +704,12 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
 
                if (!default_mounts[i].destination) {
                        ERROR("BUG: auto mounts destination %d was NULL", i);
-                       free(source);
                        return -1;
                }
 
                /* will act like strdup if %r is not present */
                destination = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].destination);
                if (!destination) {
-                       saved_errno = errno;
-                       free(source);
-                       errno = saved_errno;
                        return -1;
                }
 
@@ -745,8 +727,6 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
                        SYSERROR("Failed to mount \"%s\" on \"%s\" with flags %lu", source, destination, mflags);
                }
 
-               free(source);
-               free(destination);
                if (r < 0) {
                        errno = saved_errno;
                        return -1;
@@ -837,7 +817,7 @@ static const struct dev_symlinks dev_symlinks[] = {
 static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
 {
        int i, ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
        struct stat s;
 
        for (i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) {
@@ -845,7 +825,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
 
                ret = snprintf(path, sizeof(path), "%s/dev/%s",
                               rootfs->path ? rootfs->mount : "", d->name);
-               if (ret < 0 || ret >= MAXPATHLEN)
+               if (ret < 0 || ret >= PATH_MAX)
                        return -1;
 
                /* Stat the path first. If we don't get an error accept it as
@@ -901,7 +881,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
        int i, ret;
        const struct lxc_tty_info *ttys = &conf->ttys;
        char *ttydir = ttys->dir;
-       char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
+       char path[PATH_MAX], lxcpath[PATH_MAX];
 
        if (!conf->rootfs.path)
                return 0;
@@ -1082,7 +1062,7 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
                if (ret < 0)
                        break;
 
-               TRACE("Sent ty \"%s\" with master fd %d and slave fd %d to "
+               TRACE("Sent tty \"%s\" with master fd %d and slave fd %d to "
                      "parent", tty->name, tty->master, tty->slave);
        }
 
@@ -1139,16 +1119,16 @@ on_error:
 static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
                         const char *lxcpath)
 {
+       __do_free char *path = NULL;
        int ret;
        size_t clen;
-       char *path;
        mode_t cur_mask;
 
        INFO("Preparing \"/dev\"");
 
        /* $(rootfs->mount) + "/dev/pts" + '\0' */
        clen = (rootfs->path ? strlen(rootfs->mount) : 0) + 9;
-       path = alloca(clen);
+       path = must_realloc(NULL, clen);
 
        ret = snprintf(path, clen, "%s/dev", rootfs->path ? rootfs->mount : "");
        if (ret < 0 || (size_t)ret >= clen)
@@ -1222,13 +1202,13 @@ enum {
 static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
 {
        int i, ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
        mode_t cmask;
        int use_mknod = LXC_DEVNODE_MKNOD;
 
-       ret = snprintf(path, MAXPATHLEN, "%s/dev",
+       ret = snprintf(path, PATH_MAX, "%s/dev",
                       rootfs->path ? rootfs->mount : "");
-       if (ret < 0 || ret >= MAXPATHLEN)
+       if (ret < 0 || ret >= PATH_MAX)
                return -1;
 
        /* ignore, just don't try to fill in */
@@ -1239,12 +1219,12 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
 
        cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
        for (i = 0; i < sizeof(lxc_devices) / sizeof(lxc_devices[0]); i++) {
-               char hostpath[MAXPATHLEN];
+               char hostpath[PATH_MAX];
                const struct lxc_device_node *device = &lxc_devices[i];
 
-               ret = snprintf(path, MAXPATHLEN, "%s/dev/%s",
+               ret = snprintf(path, PATH_MAX, "%s/dev/%s",
                               rootfs->path ? rootfs->mount : "", device->name);
-               if (ret < 0 || ret >= MAXPATHLEN)
+               if (ret < 0 || ret >= PATH_MAX)
                        return -1;
 
                if (use_mknod >= LXC_DEVNODE_MKNOD) {
@@ -1271,7 +1251,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
                                 */
                                ret = open(path, O_RDONLY | O_CLOEXEC);
                                if (ret >= 0) {
-                                       close(ret);
+                                       close_prot_errno_disarm(ret);
                                        /* Device nodes are fully useable. */
                                        use_mknod = LXC_DEVNODE_OPEN;
                                        continue;
@@ -1296,8 +1276,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
                }
 
                /* Fallback to bind-mounting the device from the host. */
-               ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", device->name);
-               if (ret < 0 || ret >= MAXPATHLEN)
+               ret = snprintf(hostpath, PATH_MAX, "/dev/%s", device->name);
+               if (ret < 0 || ret >= PATH_MAX)
                        return -1;
 
                ret = safe_mount(hostpath, path, 0, MS_BIND, NULL,
@@ -1365,13 +1345,14 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
 
 int lxc_chroot(const struct lxc_rootfs *rootfs)
 {
+       __do_free char *nroot = NULL;
        int i, ret;
        char *p, *p2;
-       char buf[LXC_LINELEN], nroot[PATH_MAX];
-       FILE *f;
+       char buf[LXC_LINELEN];
        char *root = rootfs->mount;
 
-       if (!realpath(root, nroot)) {
+       nroot = realpath(root, NULL);
+       if (!nroot) {
                SYSERROR("Failed to resolve \"%s\"", root);
                return -1;
        }
@@ -1395,17 +1376,18 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
                return -1;
        }
 
-       /* The following code cleans up inhereted mounts which are not required
+       /* The following code cleans up inherited mounts which are not required
         * for CT.
         *
         * The mountinfo file shows not all mounts, if a few points have been
         * unmounted between read operations from the mountinfo. So we need to
         * read mountinfo a few times.
         *
-        * This loop can be skipped if a container uses unserns, because all
+        * This loop can be skipped if a container uses userns, because all
         * inherited mounts are locked and we should live with all this trash.
         */
        for (;;) {
+               __do_fclose FILE *f = NULL;
                int progress = 0;
 
                f = fopen("./proc/self/mountinfo", "r");
@@ -1439,13 +1421,11 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
                                progress++;
                }
 
-               fclose(f);
-
                if (!progress)
                        break;
        }
 
-       /* This also can be skipped if a container uses unserns. */
+       /* This also can be skipped if a container uses userns. */
        (void)umount2("./proc", MNT_DETACH);
 
        /* It is weird, but chdir("..") moves us in a new root */
@@ -1492,34 +1472,33 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
  */
 static int lxc_pivot_root(const char *rootfs)
 {
-       int newroot = -1, oldroot = -1, ret = -1;
+       __do_close_prot_errno int oldroot = -EBADF, newroot = -EBADF;
+       int ret;
 
-       oldroot = open("/", O_DIRECTORY | O_RDONLY);
+       oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
        if (oldroot < 0) {
                SYSERROR("Failed to open old root directory");
                return -1;
        }
 
-       newroot = open(rootfs, O_DIRECTORY | O_RDONLY);
+       newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
        if (newroot < 0) {
                SYSERROR("Failed to open new root directory");
-               goto on_error;
+               return -1;
        }
 
        /* change into new root fs */
        ret = fchdir(newroot);
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to change to new rootfs \"%s\"", rootfs);
-               goto on_error;
+               return -1;
        }
 
        /* pivot_root into our new root fs */
        ret = pivot_root(".", ".");
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to pivot_root()");
-               goto on_error;
+               return -1;
        }
 
        /* At this point the old-root is mounted on top of our new-root. To
@@ -1528,9 +1507,8 @@ static int lxc_pivot_root(const char *rootfs)
         */
        ret = fchdir(oldroot);
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to enter old root directory");
-               goto on_error;
+               return -1;
        }
 
        /* Make oldroot rslave to make sure our umounts don't propagate to the
@@ -1538,36 +1516,25 @@ static int lxc_pivot_root(const char *rootfs)
         */
        ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL);
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to make oldroot rslave");
-               goto on_error;
+               return -1;
        }
 
        ret = umount2(".", MNT_DETACH);
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to detach old root directory");
-               goto on_error;
+               return -1;
        }
 
        ret = fchdir(newroot);
        if (ret < 0) {
-               ret = -1;
                SYSERROR("Failed to re-enter new root directory");
-               goto on_error;
+               return -1;
        }
 
-       ret = 0;
-
        TRACE("pivot_root(\"%s\") successful", rootfs);
 
-on_error:
-       if (oldroot != -1)
-               close(oldroot);
-       if (newroot != -1)
-               close(newroot);
-
-       return ret;
+       return 0;
 }
 
 static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs)
@@ -1633,11 +1600,7 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
        if (ret < 0 || (size_t)ret >= sizeof(devpts_mntopts))
                return -1;
 
-       ret = umount2("/dev/pts", MNT_DETACH);
-       if (ret < 0)
-               SYSWARN("Failed to unmount old devpts instance");
-       else
-               DEBUG("Unmounted old devpts instance");
+       (void)umount2("/dev/pts", MNT_DETACH);
 
        /* Create mountpoint for devpts instance. */
        ret = mkdir("/dev/pts", 0755);
@@ -1650,13 +1613,13 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
        mntopt_sets[0] = devpts_mntopts;
 
        /* !gid=5 && max= */
-       mntopt_sets[1] = devpts_mntopts + sizeof("gid=5");
+       mntopt_sets[1] = devpts_mntopts + STRLITERALLEN("gid=5") + 1;
 
        /* gid=5 && !max= */
        mntopt_sets[2] = default_devpts_mntopts;
 
        /* !gid=5 && !max= */
-       mntopt_sets[3] = default_devpts_mntopts + sizeof("gid=5");
+       mntopt_sets[3] = default_devpts_mntopts + STRLITERALLEN("gid=5") + 1;
 
        /* end */
        mntopt_sets[4] = NULL;
@@ -1745,7 +1708,7 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
                                 const struct lxc_terminal *console)
 {
        int ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
        char *rootfs_path = rootfs->path ? rootfs->mount : "";
 
        if (console->path && !strcmp(console->path, "none"))
@@ -1799,7 +1762,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
                                    char *ttydir)
 {
        int ret;
-       char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
+       char path[PATH_MAX], lxcpath[PATH_MAX];
        char *rootfs_path = rootfs->path ? rootfs->mount : "";
 
        if (console->path && !strcmp(console->path, "none"))
@@ -1909,7 +1872,8 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data, size_t si
 
 int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata)
 {
-       char *data, *p, *s;
+       __do_free char *data = NULL, *s = NULL;
+       char *p;
        size_t size;
 
        *mntdata = NULL;
@@ -1924,20 +1888,15 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata)
 
        size = strlen(s) + 1;
        data = malloc(size);
-       if (!data) {
-               free(s);
+       if (!data)
                return -1;
-       }
        *data = 0;
 
        lxc_iterate_parts(p, s, ",")
                parse_mntopt(p, mntflags, &data, size);
 
        if (*data)
-               *mntdata = data;
-       else
-               free(data);
-       free(s);
+               *mntdata = move_ptr(data);
 
        return 0;
 }
@@ -1962,7 +1921,8 @@ static void parse_propagationopt(char *opt, unsigned long *flags)
 
 int parse_propagationopts(const char *mntopts, unsigned long *pflags)
 {
-       char *p, *s;
+       __do_free char *s = NULL;
+       char *p;
 
        if (!mntopts)
                return 0;
@@ -1976,7 +1936,6 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags)
        *pflags = 0L;
        lxc_iterate_parts(p, s, ",")
                parse_propagationopt(p, pflags);
-       free(s);
 
        return 0;
 }
@@ -2013,15 +1972,15 @@ static int mount_entry(const char *fsname, const char *target,
                       bool dev, bool relative, const char *rootfs)
 {
        int ret;
-       char srcbuf[MAXPATHLEN];
+       char srcbuf[PATH_MAX];
        const char *srcpath = fsname;
 #ifdef HAVE_STATVFS
        struct statvfs sb;
 #endif
 
        if (relative) {
-               ret = snprintf(srcbuf, MAXPATHLEN, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
-               if (ret < 0 || ret >= MAXPATHLEN) {
+               ret = snprintf(srcbuf, PATH_MAX, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
+               if (ret < 0 || ret >= PATH_MAX) {
                        ERROR("source path is too long");
                        return -1;
                }
@@ -2100,6 +2059,9 @@ static int mount_entry(const char *fsname, const char *target,
                }
        }
 
+#ifdef HAVE_STATVFS
+skipremount:
+#endif
        if (pflags) {
                ret = mount(NULL, target, NULL, pflags, NULL);
                if (ret < 0) {
@@ -2116,10 +2078,6 @@ static int mount_entry(const char *fsname, const char *target,
                DEBUG("Changed mount propagation for \"%s\"", target);
        }
 
-
-#ifdef HAVE_STATVFS
-skipremount:
-#endif
        DEBUG("Mounted \"%s\" on \"%s\" with filesystem type \"%s\"",
              srcpath ? srcpath : "(null)", target, fstype);
 
@@ -2161,8 +2119,9 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
                                       const struct lxc_rootfs *rootfs,
                                       const char *lxc_name, const char *lxc_path)
 {
+       __do_free char *p1 = NULL;
        int ret;
-       char *p1, *p2;
+       char *p2;
 
        if (strncmp(mntent->mnt_type, "overlay", 7) == 0) {
                ret = ovl_mkdir(mntent, rootfs, lxc_name, lxc_path);
@@ -2192,7 +2151,6 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
        p2 = dirname(p1);
 
        ret = mkdir_p(p2, 0755);
-       free(p1);
        if (ret < 0 && errno != EEXIST) {
                SYSERROR("Failed to create directory \"%s\"", path);
                return -1;
@@ -2213,9 +2171,9 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
                                         const char *lxc_name,
                                         const char *lxc_path)
 {
+       __do_free char *mntdata = NULL;
        int ret;
        unsigned long mntflags;
-       char *mntdata;
        bool dev, optional, relative;
        unsigned long pflags = 0;
        char *rootfs_path = NULL;
@@ -2248,14 +2206,13 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
        ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags,
                          pflags, mntdata, optional, dev, relative, rootfs_path);
 
-       free(mntdata);
        return ret;
 }
 
 static inline int mount_entry_on_systemfs(struct mntent *mntent)
 {
        int ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
 
        /* For containers created without a rootfs all mounts are treated as
         * absolute paths starting at / on the host.
@@ -2278,7 +2235,7 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
        int offset;
        char *aux;
        const char *lxcpath;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
        int ret = 0;
 
        lxcpath = lxc_global_config_value("lxc.lxcpath");
@@ -2288,8 +2245,8 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
        /* If rootfs->path is a blockdev path, allow container fstab to use
         * <lxcpath>/<name>/rootfs" as the target prefix.
         */
-       ret = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
-       if (ret < 0 || ret >= MAXPATHLEN)
+       ret = snprintf(path, PATH_MAX, "%s/%s/rootfs", lxcpath, lxc_name);
+       if (ret < 0 || ret >= PATH_MAX)
                goto skipvarlib;
 
        aux = strstr(mntent->mnt_dir, path);
@@ -2307,8 +2264,8 @@ skipvarlib:
        offset = strlen(rootfs->path);
 
 skipabs:
-       ret = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount, aux + offset);
-       if (ret < 0 || ret >= MAXPATHLEN)
+       ret = snprintf(path, PATH_MAX, "%s/%s", rootfs->mount, aux + offset);
+       if (ret < 0 || ret >= PATH_MAX)
                return -1;
 
        return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path);
@@ -2320,7 +2277,7 @@ static int mount_entry_on_relative_rootfs(struct mntent *mntent,
                                          const char *lxc_path)
 {
        int ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
 
        /* relative to root mount point */
        ret = snprintf(path, sizeof(path), "%s/%s", rootfs->mount, mntent->mnt_dir);
@@ -2334,11 +2291,12 @@ static int mount_file_entries(const struct lxc_conf *conf,
                              const struct lxc_rootfs *rootfs, FILE *file,
                              const char *lxc_name, const char *lxc_path)
 {
-       char buf[4096];
+       char buf[PATH_MAX];
        struct mntent mntent;
-       int ret = -1;
 
        while (getmntent_r(file, &mntent, buf, sizeof(buf))) {
+               int ret;
+
                if (!rootfs->path)
                        ret = mount_entry_on_systemfs(&mntent);
                else if (mntent.mnt_dir[0] != '/')
@@ -2346,14 +2304,17 @@ static int mount_file_entries(const struct lxc_conf *conf,
                                                             lxc_name, lxc_path);
                else
                        ret = mount_entry_on_absolute_rootfs(&mntent, rootfs,
-                                                            lxc_name, lxc_path);
+                                                            lxc_name, lxc_path);
                if (ret < 0)
                        return -1;
        }
-       ret = 0;
 
-       INFO("Finished setting up mounts");
-       return ret;
+       if (!feof(file) || ferror(file)) {
+               ERROR("Failed to parse mount entries");
+               return -1;
+       }
+
+       return 0;
 }
 
 static int setup_mount(const struct lxc_conf *conf,
@@ -2391,17 +2352,16 @@ static int setup_mount(const struct lxc_conf *conf,
  * access them as a side effect without explicitly allowing it.
  */
 static const char nesting_helpers[] =
-"proc dev/.lxc/proc proc create=dir,optional\n"
-"sys dev/.lxc/sys sysfs create=dir,optional\n"
-;
+"proc dev/.lxc/proc proc create=dir,optional 0 0\n"
+"sys dev/.lxc/sys sysfs create=dir,optional 0 0\n";
 
 FILE *make_anonymous_mount_file(struct lxc_list *mount,
                                bool include_nesting_helpers)
 {
+       __do_close_prot_errno int fd = -EBADF;
        int ret;
        char *mount_entry;
        struct lxc_list *iterator;
-       int fd = -1;
 
        fd = memfd_create(".lxc_mount_file", MFD_CLOEXEC);
        if (fd < 0) {
@@ -2418,10 +2378,6 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
 
                TRACE("Created temporary mount file");
        }
-       if (fd < 0) {
-               SYSERROR("Could not create temporary mount file");
-               return NULL;
-       }
 
        lxc_list_for_each (iterator, mount) {
                size_t len;
@@ -2431,30 +2387,25 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
 
                ret = lxc_write_nointr(fd, mount_entry, len);
                if (ret != len)
-                       goto on_error;
+                       return NULL;
 
                ret = lxc_write_nointr(fd, "\n", 1);
                if (ret != 1)
-                       goto on_error;
+                       return NULL;
        }
 
        if (include_nesting_helpers) {
                ret = lxc_write_nointr(fd, nesting_helpers,
-                                      sizeof(nesting_helpers) - 1);
-               if (ret != sizeof(nesting_helpers) - 1)
-                       goto on_error;
+                                      STRARRAYLEN(nesting_helpers));
+               if (ret != STRARRAYLEN(nesting_helpers))
+                       return NULL;
        }
 
        ret = lseek(fd, 0, SEEK_SET);
        if (ret < 0)
-               goto on_error;
-
-       return fdopen(fd, "r+");
+               return NULL;
 
-on_error:
-       SYSERROR("Failed to write mount entry to temporary mount file");
-       close(fd);
-       return NULL;
+       return fdopen(move_fd(fd), "r+");
 }
 
 static int setup_mount_entries(const struct lxc_conf *conf,
@@ -2462,17 +2413,13 @@ static int setup_mount_entries(const struct lxc_conf *conf,
                               struct lxc_list *mount, const char *lxc_name,
                               const char *lxc_path)
 {
-       int ret;
-       FILE *f;
+       __do_fclose FILE *f = NULL;
 
        f = make_anonymous_mount_file(mount, conf->lsm_aa_allow_nesting);
        if (!f)
                return -1;
 
-       ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path);
-       fclose(f);
-
-       return ret;
+       return mount_file_entries(conf, rootfs, f, lxc_name, lxc_path);
 }
 
 static int parse_cap(const char *cap)
@@ -2558,6 +2505,7 @@ static int setup_caps(struct lxc_list *caps)
 
 static int dropcaps_except(struct lxc_list *caps)
 {
+       __do_free int *caplist = NULL;
        int i, capid, numcaps;
        char *keep_entry;
        struct lxc_list *iterator;
@@ -2568,7 +2516,7 @@ static int dropcaps_except(struct lxc_list *caps)
        TRACE("Found %d capabilities", numcaps);
 
        /* caplist[i] is 1 if we keep capability i */
-       int *caplist = alloca(numcaps * sizeof(int));
+       caplist = must_realloc(NULL, numcaps * sizeof(int));
        memset(caplist, 0, numcaps * sizeof(int));
 
        lxc_list_for_each (iterator, caps) {
@@ -2646,8 +2594,10 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid)
                        SYSERROR("Failed to set limit %s", lim->resource);
                        return -1;
                }
+
+               TRACE("Setup \"%s\" limit", lim->resource);
 #else
-               ERROR("Cannot set limit %s as prlimit is missing", lim->resource);
+               ERROR("Cannot set limit \"%s\" as prlimit is missing", lim->resource);
                return -1;
 #endif
        }
@@ -2657,11 +2607,11 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid)
 
 int setup_sysctl_parameters(struct lxc_list *sysctls)
 {
+       __do_free char *tmp = NULL;
        struct lxc_list *it;
        struct lxc_sysctl *elem;
        int ret = 0;
-       char *tmp = NULL;
-       char filename[MAXPATHLEN] = {0};
+       char filename[PATH_MAX] = {0};
 
        lxc_list_for_each (it, sysctls) {
                elem = it->elem;
@@ -2672,7 +2622,6 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
                }
 
                ret = snprintf(filename, sizeof(filename), "/proc/sys/%s", tmp);
-               free(tmp);
                if (ret < 0 || (size_t)ret >= sizeof(filename)) {
                        ERROR("Error setting up sysctl parameters path");
                        return -1;
@@ -2681,8 +2630,8 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
                ret = lxc_write_to_file(filename, elem->value,
                                        strlen(elem->value), false, 0666);
                if (ret < 0) {
-                       ERROR("Failed to setup sysctl parameters %s to %s",
-                             elem->key, elem->value);
+                       SYSERROR("Failed to setup sysctl parameters %s to %s",
+                                elem->key, elem->value);
                        return -1;
                }
        }
@@ -2692,11 +2641,11 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
 
 int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
 {
+       __do_free char *tmp = NULL;
        struct lxc_list *it;
        struct lxc_proc *elem;
        int ret = 0;
-       char *tmp = NULL;
-       char filename[MAXPATHLEN] = {0};
+       char filename[PATH_MAX] = {0};
 
        lxc_list_for_each (it, procs) {
                elem = it->elem;
@@ -2707,7 +2656,6 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
                }
 
                ret = snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, tmp);
-               free(tmp);
                if (ret < 0 || (size_t)ret >= sizeof(filename)) {
                        ERROR("Error setting up proc filesystem path");
                        return -1;
@@ -2716,8 +2664,8 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
                ret = lxc_write_to_file(filename, elem->value,
                                        strlen(elem->value), false, 0666);
                if (ret < 0) {
-                       ERROR("Failed to setup proc filesystem %s to %s",
-                             elem->filename, elem->value);
+                       SYSERROR("Failed to setup proc filesystem %s to %s",
+                                elem->filename, elem->value);
                        return -1;
                }
        }
@@ -2804,39 +2752,37 @@ struct lxc_conf *lxc_conf_init(void)
 int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                     size_t buf_size)
 {
-       int fd, ret;
-       char path[MAXPATHLEN];
+       __do_close_prot_errno int fd;
+       int ret;
+       char path[PATH_MAX];
 
        if (geteuid() != 0 && idtype == ID_TYPE_GID) {
-               size_t buflen;
+               __do_close_prot_errno int setgroups_fd = -EBADF;
 
-               ret = snprintf(path, MAXPATHLEN, "/proc/%d/setgroups", pid);
-               if (ret < 0 || ret >= MAXPATHLEN)
+               ret = snprintf(path, PATH_MAX, "/proc/%d/setgroups", pid);
+               if (ret < 0 || ret >= PATH_MAX)
                        return -E2BIG;
 
-               fd = open(path, O_WRONLY);
-               if (fd < 0 && errno != ENOENT) {
+               setgroups_fd = open(path, O_WRONLY);
+               if (setgroups_fd < 0 && errno != ENOENT) {
                        SYSERROR("Failed to open \"%s\"", path);
                        return -1;
                }
 
-               if (fd >= 0) {
-                       buflen = sizeof("deny\n") - 1;
-                       errno = 0;
-                       ret = lxc_write_nointr(fd, "deny\n", buflen);
-                       close(fd);
-                       if (ret != buflen) {
-                               SYSERROR("Failed to write \"deny\" to "
-                                        "\"/proc/%d/setgroups\"", pid);
+               if (setgroups_fd >= 0) {
+                       ret = lxc_write_nointr(setgroups_fd, "deny\n",
+                                              STRLITERALLEN("deny\n"));
+                       if (ret != STRLITERALLEN("deny\n")) {
+                               SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid);
                                return -1;
                        }
                        TRACE("Wrote \"deny\" to \"/proc/%d/setgroups\"", pid);
                }
        }
 
-       ret = snprintf(path, MAXPATHLEN, "/proc/%d/%cid_map", pid,
+       ret = snprintf(path, PATH_MAX, "/proc/%d/%cid_map", pid,
                       idtype == ID_TYPE_UID ? 'u' : 'g');
-       if (ret < 0 || ret >= MAXPATHLEN)
+       if (ret < 0 || ret >= PATH_MAX)
                return -E2BIG;
 
        fd = open(path, O_WRONLY);
@@ -2845,9 +2791,7 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                return -1;
        }
 
-       errno = 0;
        ret = lxc_write_nointr(fd, buf, buf_size);
-       close(fd);
        if (ret != buf_size) {
                SYSERROR("Failed to write %cid mapping to \"%s\"",
                         idtype == ID_TYPE_UID ? 'u' : 'g', path);
@@ -2866,29 +2810,28 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
  */
 static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
 {
-       char *path;
+       __do_free char *path = NULL;
        int ret;
        struct stat st;
        int fret = 0;
 
+       errno = EINVAL;
        if (cap != CAP_SETUID && cap != CAP_SETGID)
-               return -EINVAL;
+               return -1;
 
+       errno = ENOENT;
        path = on_path(binary, NULL);
        if (!path)
-               return -ENOENT;
+               return -1;
 
        ret = stat(path, &st);
-       if (ret < 0) {
-               fret = -errno;
-               goto cleanup;
-       }
+       if (ret < 0)
+               return -1;
 
        /* Check if the binary is setuid. */
        if (st.st_mode & S_ISUID) {
                DEBUG("The binary \"%s\" does have the setuid bit set", path);
-               fret = 1;
-               goto cleanup;
+               return 1;
        }
 
 #if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES
@@ -2898,8 +2841,7 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
            lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED)) {
                DEBUG("The binary \"%s\" has CAP_SETUID in its CAP_EFFECTIVE "
                      "and CAP_PERMITTED sets", path);
-               fret = 1;
-               goto cleanup;
+               return 1;
        }
 
        /* Check if it has the CAP_SETGID capability. */
@@ -2908,22 +2850,18 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
            lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED)) {
                DEBUG("The binary \"%s\" has CAP_SETGID in its CAP_EFFECTIVE "
                      "and CAP_PERMITTED sets", path);
-               fret = 1;
-               goto cleanup;
+               return 1;
        }
 #else
        /* If we cannot check for file capabilities we need to give the benefit
         * of the doubt. Otherwise we might fail even though all the necessary
         * file capabilities are set.
         */
-       DEBUG("Cannot check for file capabilites as full capability support is "
+       DEBUG("Cannot check for file capabilities as full capability support is "
              "missing. Manual intervention needed");
-       fret = 1;
 #endif
 
-cleanup:
-       free(path);
-       return fret;
+       return 1;
 }
 
 int lxc_map_ids_exec_wrapper(void *args)
@@ -2937,7 +2875,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
        int fill, left;
        char u_or_g;
        char *pos;
-       char cmd_output[MAXPATHLEN];
+       char cmd_output[PATH_MAX];
        struct id_map *map;
        struct lxc_list *iterator;
        enum idtype type;
@@ -3040,7 +2978,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
                if (!had_entry)
                        continue;
 
-               /* Try to catch the ouput of new{g,u}idmap to make debugging
+               /* Try to catch the output of new{g,u}idmap to make debugging
                 * easier.
                 */
                if (use_shadow) {
@@ -3170,7 +3108,7 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
                         "-m", map5,
                         "--", "chown", ugid, path,
                         NULL};
-       char cmd_output[MAXPATHLEN];
+       char cmd_output[PATH_MAX];
 
        hostuid = geteuid();
        hostgid = getegid();
@@ -3311,11 +3249,12 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf)
 /* Walk /proc/mounts and change any shared entries to slave. */
 void remount_all_slave(void)
 {
-       int memfd, mntinfo_fd, ret;
+       __do_free char *line = NULL;
+       __do_fclose FILE *f = NULL;
+       __do_close_prot_errno int memfd = -EBADF, mntinfo_fd = -EBADF;
+       int ret;
        ssize_t copied;
-       FILE *f;
        size_t len = 0;
-       char *line = NULL;
 
        mntinfo_fd = open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC);
        if (mntinfo_fd < 0) {
@@ -3329,52 +3268,45 @@ void remount_all_slave(void)
 
                if (errno != ENOSYS) {
                        SYSERROR("Failed to create temporary in-memory file");
-                       close(mntinfo_fd);
                        return;
                }
 
                memfd = lxc_make_tmpfile(template, true);
                if (memfd < 0) {
-                       close(mntinfo_fd);
                        WARN("Failed to create temporary file");
                        return;
                }
        }
 
-#define __LXC_SENDFILE_MAX 0x7ffff000 /* maximum number of bytes sendfile can handle */
 again:
-       copied = sendfile(memfd, mntinfo_fd, NULL, __LXC_SENDFILE_MAX);
+       copied = lxc_sendfile_nointr(memfd, mntinfo_fd, NULL, LXC_SENDFILE_MAX);
        if (copied < 0) {
                if (errno == EINTR)
                        goto again;
 
                SYSERROR("Failed to copy \"/proc/self/mountinfo\"");
-               close(mntinfo_fd);
-               close(memfd);
                return;
        }
-       close(mntinfo_fd);
 
-       /* After a successful fdopen() memfd will be closed when calling
-        * fclose(f). Calling close(memfd) afterwards is undefined.
-        */
        ret = lseek(memfd, 0, SEEK_SET);
        if (ret < 0) {
                SYSERROR("Failed to reset file descriptor offset");
-               close(memfd);
                return;
        }
 
        f = fdopen(memfd, "r");
        if (!f) {
-               SYSERROR("Failed to open copy of \"/proc/self/mountinfo\" to mark "
-                               "all shared. Continuing");
-               close(memfd);
+               SYSERROR("Failed to open copy of \"/proc/self/mountinfo\" to mark all shared. Continuing");
                return;
        }
 
+       /*
+        * After a successful fdopen() memfd will be closed when calling
+        * fclose(f). Calling close(memfd) afterwards is undefined.
+        */
+       move_fd(memfd);
+
        while (getline(&line, &len, f) != -1) {
-               int ret;
                char *opts, *target;
 
                target = get_field(line, 4);
@@ -3398,8 +3330,6 @@ again:
                }
                TRACE("Remounted \"%s\" as MS_SLAVE", target);
        }
-       fclose(f);
-       free(line);
        TRACE("Remounted all mount table entries as MS_SLAVE");
 }
 
@@ -3413,10 +3343,9 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
        /* If init exists in the container, don't bind mount a static one */
        p = choose_init(conf->rootfs.mount);
        if (p) {
-               char *old = p;
+               __do_free char *old = p;
 
                p = strdup(old + strlen(conf->rootfs.mount));
-               free(old);
                if (!p)
                        return -ENOMEM;
 
@@ -3506,23 +3435,22 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
 
 static bool verify_start_hooks(struct lxc_conf *conf)
 {
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
        struct lxc_list *it;
 
        lxc_list_for_each (it, &conf->hooks[LXCHOOK_START]) {
                int ret;
-               struct stat st;
                char *hookname = it->elem;
 
-               ret = snprintf(path, MAXPATHLEN, "%s%s",
+               ret = snprintf(path, PATH_MAX, "%s%s",
                               conf->rootfs.path ? conf->rootfs.mount : "",
                               hookname);
-               if (ret < 0 || ret >= MAXPATHLEN)
+               if (ret < 0 || ret >= PATH_MAX)
                        return false;
 
-               ret = stat(path, &st);
+               ret = access(path, X_OK);
                if (ret < 0) {
-                       SYSERROR("Start hook %s not found in container",
+                       SYSERROR("Start hook \"%s\" not found in container",
                                 hookname);
                        return false;
                }
@@ -3535,21 +3463,11 @@ static bool verify_start_hooks(struct lxc_conf *conf)
 
 static bool execveat_supported(void)
 {
-#ifdef __NR_execveat
-       /*
-        * We use the syscall here, because it was introduced in kernel 3.19,
-        * while glibc got support for using the syscall much later, in 2.27.
-        * We don't want to use glibc because it falls back to /proc, and the
-        * container may not have /proc mounted depending on its configuration.
-        */
-       syscall(__NR_execveat, -1, "", NULL, NULL, AT_EMPTY_PATH);
+       lxc_raw_execveat(-1, "", NULL, NULL, AT_EMPTY_PATH);
        if (errno == ENOSYS)
                return false;
 
        return true;
-#else
-       return false;
-#endif
 }
 
 int lxc_setup(struct lxc_handler *handler)
@@ -3572,6 +3490,10 @@ int lxc_setup(struct lxc_handler *handler)
                }
        }
 
+       ret = lxc_setup_keyring();
+       if (ret < 0)
+               return -1;
+
        ret = lxc_setup_network_in_child_namespaces(lxc_conf, &lxc_conf->network);
        if (ret < 0) {
                ERROR("Failed to setup network");
@@ -3607,10 +3529,6 @@ int lxc_setup(struct lxc_handler *handler)
                return -1;
        }
 
-       /* Make sure any start hooks are in the container */
-       if (!verify_start_hooks(lxc_conf))
-               return -1;
-
        if (lxc_conf->is_execute) {
                if (execveat_supported()) {
                        int fd;
@@ -3678,6 +3596,12 @@ int lxc_setup(struct lxc_handler *handler)
                }
        }
 
+       /* Make sure any start hooks are in the container */
+       if (!verify_start_hooks(lxc_conf)) {
+               ERROR("Failed to verify start hooks");
+               return -1;
+       }
+
        ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
                                lxc_conf->ttys.dir);
        if (ret < 0) {
@@ -3839,6 +3763,16 @@ int lxc_clear_config_keepcaps(struct lxc_conf *c)
        return 0;
 }
 
+int lxc_clear_namespace(struct lxc_conf *c)
+{
+       int i;
+       for (i = 0; i < LXC_NS_MAX; i++) {
+               free(c->ns_share[i]);
+               c->ns_share[i] = NULL;
+       }
+       return 0;
+}
+
 int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
 {
        char *global_token, *namespaced_token;
@@ -3850,12 +3784,12 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
        if (version == CGROUP2_SUPER_MAGIC) {
                global_token = "lxc.cgroup2";
                namespaced_token = "lxc.cgroup2.";
-               namespaced_token_len = sizeof("lxc.cgroup2.") - 1;
+               namespaced_token_len = STRLITERALLEN("lxc.cgroup2.");
                list = &c->cgroup2;
        } else if (version == CGROUP_SUPER_MAGIC) {
                global_token = "lxc.cgroup";
                namespaced_token = "lxc.cgroup.";
-               namespaced_token_len = sizeof("lxc.cgroup.") - 1;
+               namespaced_token_len = STRLITERALLEN("lxc.cgroup.");
                list = &c->cgroup;
        } else {
                return -EINVAL;
@@ -3863,7 +3797,7 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
 
        if (strcmp(key, global_token) == 0)
                all = true;
-       else if (strncmp(key, namespaced_token, sizeof(namespaced_token) - 1) == 0)
+       else if (strncmp(key, namespaced_token, namespaced_token_len) == 0)
                k += namespaced_token_len;
        else
                return -EINVAL;
@@ -3892,10 +3826,10 @@ int lxc_clear_limits(struct lxc_conf *c, const char *key)
 
        if (strcmp(key, "lxc.limit") == 0 || strcmp(key, "lxc.prlimit") == 0)
                all = true;
-       else if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.") - 1) == 0)
-               k = key + sizeof("lxc.limit.") - 1;
-       else if (strncmp(key, "lxc.prlimit.", sizeof("lxc.prlimit.") - 1) == 0)
-               k = key + sizeof("lxc.prlimit.") - 1;
+       else if (strncmp(key, "lxc.limit.", STRLITERALLEN("lxc.limit.")) == 0)
+               k = key + STRLITERALLEN("lxc.limit.");
+       else if (strncmp(key, "lxc.prlimit.", STRLITERALLEN("lxc.prlimit.")) == 0)
+               k = key + STRLITERALLEN("lxc.prlimit.");
        else
                return -1;
 
@@ -3922,8 +3856,8 @@ int lxc_clear_sysctls(struct lxc_conf *c, const char *key)
 
        if (strcmp(key, "lxc.sysctl") == 0)
                all = true;
-       else if (strncmp(key, "lxc.sysctl.", sizeof("lxc.sysctl.") - 1) == 0)
-               k = key + sizeof("lxc.sysctl.") - 1;
+       else if (strncmp(key, "lxc.sysctl.", STRLITERALLEN("lxc.sysctl.")) == 0)
+               k = key + STRLITERALLEN("lxc.sysctl.");
        else
                return -1;
 
@@ -3951,8 +3885,8 @@ int lxc_clear_procs(struct lxc_conf *c, const char *key)
 
        if (strcmp(key, "lxc.proc") == 0)
                all = true;
-       else if (strncmp(key, "lxc.proc.", sizeof("lxc.proc.") - 1) == 0)
-               k = key + sizeof("lxc.proc.") - 1;
+       else if (strncmp(key, "lxc.proc.", STRLITERALLEN("lxc.proc.")) == 0)
+               k = key + STRLITERALLEN("lxc.proc.");
        else
                return -1;
 
@@ -4026,8 +3960,8 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
 
        if (strcmp(key, "lxc.hook") == 0)
                all = true;
-       else if (strncmp(key, "lxc.hook.", sizeof("lxc.hook.") - 1) == 0)
-               k = key + sizeof("lxc.hook.") - 1;
+       else if (strncmp(key, "lxc.hook.", STRLITERALLEN("lxc.hook.")) == 0)
+               k = key + STRLITERALLEN("lxc.hook.");
        else
                return -1;
 
@@ -4131,6 +4065,7 @@ void lxc_conf_free(struct lxc_conf *conf)
        lxc_clear_sysctls(conf, "lxc.sysctl");
        lxc_clear_procs(conf, "lxc.proc");
        lxc_clear_apparmor_raw(conf);
+       lxc_clear_namespace(conf);
        free(conf->cgroup_meta.dir);
        free(conf->cgroup_meta.controllers);
        free(conf->shmount.path_host);
@@ -4245,18 +4180,20 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id,
 
 struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
 {
+       __do_free struct id_map *container_root_uid = NULL,
+                               *container_root_gid = NULL,
+                               *host_uid_map = NULL, *host_gid_map = NULL;
+       __do_free struct lxc_list *idmap = NULL;
        uid_t euid, egid;
        uid_t nsuid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid;
        gid_t nsgid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid;
-       struct lxc_list *idmap = NULL, *tmplist = NULL;
-       struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
-                     *host_uid_map = NULL, *host_gid_map = NULL;
+       struct lxc_list *tmplist = NULL;
 
        /* Find container root mappings. */
        container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID);
        if (!container_root_uid) {
                DEBUG("Failed to find mapping for namespace uid %d", 0);
-               goto on_error;
+               return NULL;
        }
        euid = geteuid();
        if (euid >= container_root_uid->hostid &&
@@ -4266,7 +4203,7 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
        container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID);
        if (!container_root_gid) {
                DEBUG("Failed to find mapping for namespace gid %d", 0);
-               goto on_error;
+               return NULL;
        }
        egid = getegid();
        if (egid >= container_root_gid->hostid &&
@@ -4278,84 +4215,68 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
                host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID);
        if (!host_uid_map) {
                DEBUG("Failed to find mapping for uid %d", euid);
-               goto on_error;
+               return NULL;
        }
 
        if (!host_gid_map)
                host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
        if (!host_gid_map) {
                DEBUG("Failed to find mapping for gid %d", egid);
-               goto on_error;
+               return NULL;
        }
 
        /* Allocate new {g,u}id map list. */
        idmap = malloc(sizeof(*idmap));
        if (!idmap)
-               goto on_error;
+               return NULL;
        lxc_list_init(idmap);
 
        /* Add container root to the map. */
        tmplist = malloc(sizeof(*tmplist));
        if (!tmplist)
-               goto on_error;
+               return NULL;
        lxc_list_add_elem(tmplist, container_root_uid);
        lxc_list_add_tail(idmap, tmplist);
 
        if (host_uid_map && (host_uid_map != container_root_uid)) {
                /* idmap will now keep track of that memory. */
-               container_root_uid = NULL;
+               move_ptr(container_root_uid);
 
                /* Add container root to the map. */
                tmplist = malloc(sizeof(*tmplist));
                if (!tmplist)
-                       goto on_error;
+                       return NULL;
                lxc_list_add_elem(tmplist, host_uid_map);
                lxc_list_add_tail(idmap, tmplist);
        }
        /* idmap will now keep track of that memory. */
-       container_root_uid = NULL;
+       move_ptr(container_root_uid);
        /* idmap will now keep track of that memory. */
-       host_uid_map = NULL;
+       move_ptr(host_uid_map);
 
        tmplist = malloc(sizeof(*tmplist));
        if (!tmplist)
-               goto on_error;
+               return NULL;
        lxc_list_add_elem(tmplist, container_root_gid);
        lxc_list_add_tail(idmap, tmplist);
 
        if (host_gid_map && (host_gid_map != container_root_gid)) {
                /* idmap will now keep track of that memory. */
-               container_root_gid = NULL;
+               move_ptr(container_root_gid);
 
                tmplist = malloc(sizeof(*tmplist));
                if (!tmplist)
-                       goto on_error;
+                       return NULL;
                lxc_list_add_elem(tmplist, host_gid_map);
                lxc_list_add_tail(idmap, tmplist);
        }
        /* idmap will now keep track of that memory. */
-       container_root_gid = NULL;
+       move_ptr(container_root_gid);
        /* idmap will now keep track of that memory. */
-       host_gid_map = NULL;
+       move_ptr(host_gid_map);
 
        TRACE("Allocated minimal idmapping");
-       return idmap;
-
-on_error:
-       if (idmap) {
-               lxc_free_idmap(idmap);
-               free(idmap);
-       }
-       if (container_root_uid)
-               free(container_root_uid);
-       if (container_root_gid)
-               free(container_root_gid);
-       if (host_uid_map && (host_uid_map != container_root_uid))
-               free(host_uid_map);
-       if (host_gid_map && (host_gid_map != container_root_gid))
-               free(host_gid_map);
-
-       return NULL;
+       return move_ptr(idmap);
 }
 
 /* Run a function in a new user namespace.
@@ -4365,8 +4286,8 @@ on_error:
  * This means we require only to establish a mapping from:
  * - the container root {g,u}id as seen from the host > user's host {g,u}id
  * - the container root -> some sub{g,u}id
- * The former we add, if the user did not specifiy a mapping. The latter we
- * retrieve from the ontainer's configured {g,u}id mappings as it must have been
+ * The former we add, if the user did not specify a mapping. The latter we
+ * retrieve from the container's configured {g,u}id mappings as it must have been
  * there to start the container in the first place.
  */
 int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
@@ -4637,10 +4558,9 @@ on_error:
 /* not thread-safe, do not use from api without first forking */
 static char *getuname(void)
 {
+       __do_free char *buf = NULL;
        struct passwd pwent;
        struct passwd *pwentp = NULL;
-       char *buf;
-       char *username;
        size_t bufsize;
        int ret;
 
@@ -4658,23 +4578,18 @@ static char *getuname(void)
                        WARN("Could not find matched password record.");
 
                ERROR("Failed to get password record - %u", geteuid());
-               free(buf);
                return NULL;
        }
 
-       username = strdup(pwent.pw_name);
-       free(buf);
-
-       return username;
+       return strdup(pwent.pw_name);
 }
 
 /* not thread-safe, do not use from api without first forking */
 static char *getgname(void)
 {
+       __do_free char *buf = NULL;
        struct group grent;
        struct group *grentp = NULL;
-       char *buf;
-       char *grname;
        size_t bufsize;
        int ret;
 
@@ -4692,44 +4607,35 @@ static char *getgname(void)
                        WARN("Could not find matched group record");
 
                ERROR("Failed to get group record - %u", getegid());
-               free(buf);
                return NULL;
        }
 
-       grname = strdup(grent.gr_name);
-       free(buf);
-
-       return grname;
+       return strdup(grent.gr_name);
 }
 
 /* not thread-safe, do not use from api without first forking */
 void suggest_default_idmap(void)
 {
-       char *uname, *gname;
-       FILE *f;
+       __do_free char *gname = NULL, *line = NULL, *uname = NULL;
+       __do_fclose FILE *subuid_f = NULL, *subgid_f = NULL;
        unsigned int uid = 0, urange = 0, gid = 0, grange = 0;
        size_t len = 0;
-       char *line = NULL;
 
        uname = getuname();
        if (!uname)
                return;
 
        gname = getgname();
-       if (!gname) {
-               free(uname);
+       if (!gname)
                return;
-       }
 
-       f = fopen(subuidfile, "r");
-       if (!f) {
+       subuid_f = fopen(subuidfile, "r");
+       if (!subuid_f) {
                ERROR("Your system is not configured with subuids");
-               free(gname);
-               free(uname);
                return;
        }
 
-       while (getline(&line, &len, f) != -1) {
+       while (getline(&line, &len, subuid_f) != -1) {
                char *p, *p2;
                size_t no_newline = 0;
 
@@ -4759,17 +4665,14 @@ void suggest_default_idmap(void)
                if (lxc_safe_uint(p2, &urange) < 0)
                        WARN("Could not parse UID range");
        }
-       fclose(f);
 
-       f = fopen(subgidfile, "r");
-       if (!f) {
+       subgid_f = fopen(subgidfile, "r");
+       if (!subgid_f) {
                ERROR("Your system is not configured with subgids");
-               free(gname);
-               free(uname);
                return;
        }
 
-       while (getline(&line, &len, f) != -1) {
+       while (getline(&line, &len, subgid_f) != -1) {
                char *p, *p2;
                size_t no_newline = 0;
 
@@ -4799,15 +4702,10 @@ void suggest_default_idmap(void)
                if (lxc_safe_uint(p2, &grange) < 0)
                        WARN("Could not parse GID range");
        }
-       fclose(f);
-
-       free(line);
 
        if (!urange || !grange) {
                ERROR("You do not have subuids or subgids allocated");
                ERROR("Unprivileged containers require subuids and subgids");
-               free(uname);
-               free(gname);
                return;
        }
 
@@ -4817,9 +4715,6 @@ void suggest_default_idmap(void)
        ERROR("lxc.include = %s", LXC_DEFAULT_CONFIG);
        ERROR("lxc.idmap = u 0 %u %u", uid, urange);
        ERROR("lxc.idmap = g 0 %u %u", gid, grange);
-
-       free(gname);
-       free(uname);
 }
 
 static void free_cgroup_settings(struct lxc_list *result)