]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/conf.c
spelling: output
[mirror_lxc.git] / src / lxc / conf.c
index f5b94b091aaa9b1002899d80cb7a27a1fd4b7a4d..52ec8731b82d627578143cf47392234321455c4e 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 "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 "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"
-
-#ifndef MS_PRIVATE
-#define MS_PRIVATE (1<<18)
-#endif
-
-#ifndef MS_LAZYTIME
-#define MS_LAZYTIME (1<<25)
-#endif
-
 lxc_log_define(conf, lxc);
 
 /* The lxc_conf of the container currently being worked on in an API call.
  * This is used in the error calls.
  */
 #ifdef HAVE_TLS
-__thread struct lxc_conf *current_config;
+thread_local struct lxc_conf *current_config;
 #else
 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",
@@ -379,7 +360,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++;
 
@@ -517,7 +499,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);
@@ -560,25 +542,32 @@ int run_script(const char *name, const char *section, const char *script, ...)
 int pin_rootfs(const char *rootfs)
 {
        int fd, ret;
-       char absrootfs[MAXPATHLEN], absrootfspin[MAXPATHLEN];
+       char absrootfspin[PATH_MAX];
+       char *absrootfs;
        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);
-       if (ret < 0)
+       if (ret < 0) {
+               free(absrootfs);
                return -1;
+       }
 
-       if (!S_ISDIR(s.st_mode))
+       if (!S_ISDIR(s.st_mode)) {
+               free(absrootfs);
                return -2;
+       }
 
-       ret = snprintf(absrootfspin, MAXPATHLEN, "%s/.lxc-keep", absrootfs);
-       if (ret >= MAXPATHLEN)
+       ret = snprintf(absrootfspin, PATH_MAX, "%s/.lxc-keep", absrootfs);
+       free(absrootfs);
+       if (ret < 0 || ret >= PATH_MAX)
                return -1;
 
        fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
@@ -650,7 +639,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.
         */
@@ -701,7 +690,6 @@ 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 },
@@ -845,7 +833,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++) {
@@ -853,7 +841,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
@@ -909,7 +897,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;
@@ -928,7 +916,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
                        if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                                return -1;
 
-                       ret = mknod(path, S_IFREG | 0000, 0);
+                       ret = mknod(lxcpath, S_IFREG | 0000, 0);
                        if (ret < 0 && errno != EEXIST) {
                                SYSERROR("Failed to create \"%s\"", lxcpath);
                                return -1;
@@ -942,12 +930,12 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
 
                        ret = mount(tty->name, lxcpath, "none", MS_BIND, 0);
                        if (ret < 0) {
-                               WARN("Failed to bind mount \"%s\" onto \"%s\"",
-                                    tty->name, path);
+                               SYSWARN("Failed to bind mount \"%s\" onto \"%s\"",
+                                    tty->name, lxcpath);
                                continue;
                        }
                        DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name,
-                             path);
+                             lxcpath);
 
                        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d",
                                       ttydir, i + 1);
@@ -989,7 +977,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
 
 int lxc_allocate_ttys(struct lxc_conf *conf)
 {
-       int i, ret;
+       size_t i;
+       int ret;
        struct lxc_tty_info *ttys = &conf->ttys;
 
        /* no tty in the configuration */
@@ -1007,7 +996,7 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
                tty->slave = -EBADF;
                ret = openpty(&tty->master, &tty->slave, NULL, NULL, NULL);
                if (ret < 0) {
-                       SYSERROR("Failed to create tty %d", i);
+                       SYSERROR("Failed to create tty %zu", i);
                        ttys->max = i;
                        lxc_delete_tty(ttys);
                        return -ENOTTY;
@@ -1015,7 +1004,7 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
 
                ret = ttyname_r(tty->slave, tty->name, sizeof(tty->name));
                if (ret < 0) {
-                       SYSERROR("Failed to retrieve name of tty %d slave", i);
+                       SYSERROR("Failed to retrieve name of tty %zu slave", i);
                        ttys->max = i;
                        lxc_delete_tty(ttys);
                        return -ENOTTY;
@@ -1140,84 +1129,6 @@ on_error:
        return ret;
 }
 
-static int setup_rootfs_pivot_root(const char *rootfs)
-{
-       int ret;
-       int newroot = -1, oldroot = -1;
-
-       oldroot = open("/", O_DIRECTORY | O_RDONLY);
-       if (oldroot < 0) {
-               SYSERROR("Failed to open old root directory");
-               return -1;
-       }
-
-       newroot = open(rootfs, O_DIRECTORY | O_RDONLY);
-       if (newroot < 0) {
-               SYSERROR("Failed to open new root directory");
-               goto on_error;
-       }
-
-       /* change into new root fs */
-       ret = fchdir(newroot);
-       if (ret < 0) {
-               SYSERROR("Failed to change to new rootfs \"%s\"", rootfs);
-               goto on_error;
-       }
-
-       /* pivot_root into our new root fs */
-       ret = pivot_root(".", ".");
-       if (ret < 0) {
-               SYSERROR("Failed to pivot_root()");
-               goto on_error;
-       }
-
-       /* At this point the old-root is mounted on top of our new-root. To
-        * unmounted it we must not be chdir'd into it, so escape back to
-        * old-root.
-        */
-       ret = fchdir(oldroot);
-       if (ret < 0) {
-               SYSERROR("Failed to enter old root directory");
-               goto on_error;
-       }
-
-       /* Make oldroot rslave to make sure our umounts don't propagate to the
-        * host.
-        */
-       ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL);
-       if (ret < 0) {
-               SYSERROR("Failed to make oldroot rslave");
-               goto on_error;
-       }
-
-       ret = umount2(".", MNT_DETACH);
-       if (ret < 0) {
-               SYSERROR("Failed to detach old root directory");
-               goto on_error;
-       }
-
-       ret = fchdir(newroot);
-       if (ret < 0) {
-               SYSERROR("Failed to re-enter new root directory");
-               goto on_error;
-       }
-
-       close(oldroot);
-       close(newroot);
-
-       DEBUG("pivot_root(\"%s\") successful", rootfs);
-
-       return 0;
-
-on_error:
-       if (oldroot != -1)
-               close(oldroot);
-       if (newroot != -1)
-               close(newroot);
-
-       return -1;
-}
-
 /* Just create a path for /dev under $lxcpath/$name and in rootfs If we hit an
  * error, log it but don't fail yet.
  */
@@ -1307,13 +1218,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 */
@@ -1324,12 +1235,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) {
@@ -1381,8 +1292,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,
@@ -1401,17 +1312,16 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
        return 0;
 }
 
-static int lxc_setup_rootfs(struct lxc_conf *conf)
+static int lxc_mount_rootfs(struct lxc_conf *conf)
 {
        int ret;
        struct lxc_storage *bdev;
-       const struct lxc_rootfs *rootfs;
+       const struct lxc_rootfs *rootfs = &conf->rootfs;
 
-       rootfs = &conf->rootfs;
        if (!rootfs->path) {
                ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0);
                if (ret < 0) {
-                       SYSERROR("Failed to make / rslave");
+                       SYSERROR("Failed to remount \"/\" MS_REC | MS_SLAVE");
                        return -1;
                }
 
@@ -1449,36 +1359,45 @@ static int lxc_setup_rootfs(struct lxc_conf *conf)
        return 0;
 }
 
-int prepare_ramfs_root(char *root)
+int lxc_chroot(const struct lxc_rootfs *rootfs)
 {
        int i, ret;
        char *p, *p2;
-       char buf[LXC_LINELEN], nroot[PATH_MAX];
+       char buf[LXC_LINELEN];
+       char *nroot;
        FILE *f;
+       char *root = rootfs->mount;
 
-       if (!realpath(root, nroot))
+       nroot = realpath(root, NULL);
+       if (!nroot) {
+               SYSERROR("Failed to resolve \"%s\"", root);
                return -1;
+       }
 
        ret = chdir("/");
-       if (ret < 0)
+       if (ret < 0) {
+               free(nroot);
                return -1;
+       }
 
        /* We could use here MS_MOVE, but in userns this mount is locked and
         * can't be moved.
         */
-       ret = mount(root, "/", NULL, MS_REC | MS_BIND, NULL);
+       ret = mount(nroot, "/", NULL, MS_REC | MS_BIND, NULL);
        if (ret < 0) {
-               SYSERROR("Failed to move \"%s\" into \"/\"", root);
+               SYSERROR("Failed to mount \"%s\" onto \"/\" as MS_REC | MS_BIND", nroot);
+               free(nroot);
                return -1;
        }
+       free(nroot);
 
        ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL);
        if (ret < 0) {
-               SYSERROR("Failed to make \"/\" rprivate");
+               SYSERROR("Failed to remount \"/\"");
                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
@@ -1493,7 +1412,7 @@ int prepare_ramfs_root(char *root)
 
                f = fopen("./proc/self/mountinfo", "r");
                if (!f) {
-                       SYSERROR("Unable to open /proc/self/mountinfo");
+                       SYSERROR("Failed to open \"/proc/self/mountinfo\"");
                        return -1;
                }
 
@@ -1534,53 +1453,142 @@ int prepare_ramfs_root(char *root)
        /* It is weird, but chdir("..") moves us in a new root */
        ret = chdir("..");
        if (ret < 0) {
-               SYSERROR("Unable to change working directory");
+               SYSERROR("Failed to chdir(\"..\")");
                return -1;
        }
 
        ret = chroot(".");
        if (ret < 0) {
-               SYSERROR("Unable to chroot");
+               SYSERROR("Failed to chroot(\".\")");
                return -1;
        }
 
        return 0;
 }
 
-static int setup_pivot_root(const struct lxc_rootfs *rootfs)
+/* (The following explanation is copied verbatim from the kernel.)
+ *
+ * pivot_root Semantics:
+ * Moves the root file system of the current process to the directory put_old,
+ * makes new_root as the new root file system of the current process, and sets
+ * root/cwd of all processes which had them on the current root to new_root.
+ *
+ * Restrictions:
+ * The new_root and put_old must be directories, and  must not be on the
+ * same file  system as the current process root. The put_old  must  be
+ * underneath new_root,  i.e. adding a non-zero number of /.. to the string
+ * pointed to by put_old must yield the same directory as new_root. No other
+ * file system may be mounted on put_old. After all, new_root is a mountpoint.
+ *
+ * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
+ * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
+ * in this situation.
+ *
+ * Notes:
+ *  - we don't move root/cwd if they are not at the root (reason: if something
+ *    cared enough to change them, it's probably wrong to force them elsewhere)
+ *  - it's okay to pick a root that isn't the root of a file system, e.g.
+ *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
+ *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
+ *    first.
+ */
+static int lxc_pivot_root(const char *rootfs)
 {
-       int ret;
+       int oldroot;
+       int newroot = -1, ret = -1;
 
-       if (!rootfs->path) {
-               DEBUG("Container does not have a rootfs");
-               return 0;
+       oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+       if (oldroot < 0) {
+               SYSERROR("Failed to open old root directory");
+               return -1;
        }
 
-       if (detect_ramfs_rootfs()) {
-               DEBUG("Detected that container is on ramfs");
+       newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+       if (newroot < 0) {
+               SYSERROR("Failed to open new root directory");
+               goto on_error;
+       }
 
-               ret = prepare_ramfs_root(rootfs->mount);
-               if (ret < 0) {
-                       ERROR("Failed to prepare minimal ramfs root");
-                       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;
+       }
 
-               DEBUG("Prepared ramfs root for container");
-               return 0;
+       /* pivot_root into our new root fs */
+       ret = pivot_root(".", ".");
+       if (ret < 0) {
+               ret = -1;
+               SYSERROR("Failed to pivot_root()");
+               goto on_error;
        }
 
-       ret = setup_rootfs_pivot_root(rootfs->mount);
+       /* At this point the old-root is mounted on top of our new-root. To
+        * unmounted it we must not be chdir'd into it, so escape back to
+        * old-root.
+        */
+       ret = fchdir(oldroot);
        if (ret < 0) {
-               ERROR("Failed to pivot_root()");
-               return -1;
+               ret = -1;
+               SYSERROR("Failed to enter old root directory");
+               goto on_error;
        }
 
-       DEBUG("Finished pivot_root()");
-       return 0;
+       /* Make oldroot rslave to make sure our umounts don't propagate to the
+        * host.
+        */
+       ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL);
+       if (ret < 0) {
+               ret = -1;
+               SYSERROR("Failed to make oldroot rslave");
+               goto on_error;
+       }
+
+       ret = umount2(".", MNT_DETACH);
+       if (ret < 0) {
+               ret = -1;
+               SYSERROR("Failed to detach old root directory");
+               goto on_error;
+       }
+
+       ret = fchdir(newroot);
+       if (ret < 0) {
+               ret = -1;
+               SYSERROR("Failed to re-enter new root directory");
+               goto on_error;
+       }
+
+       ret = 0;
+
+       TRACE("pivot_root(\"%s\") successful", rootfs);
+
+on_error:
+       close(oldroot);
+
+       if (newroot >= 0)
+               close(newroot);
+
+       return ret;
+}
+
+static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs)
+{
+       if (!rootfs->path) {
+               DEBUG("Container does not have a rootfs");
+               return 0;
+       }
+
+       if (detect_ramfs_rootfs())
+               return lxc_chroot(rootfs);
+
+       return lxc_pivot_root(rootfs->mount);
 }
 
-static const struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
-                                            enum idtype idtype)
+static const struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf,
+                                                  unsigned id,
+                                                  enum idtype idtype)
 {
        struct lxc_list *it;
        struct id_map *map;
@@ -1612,8 +1620,10 @@ static const struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsign
 static int lxc_setup_devpts(struct lxc_conf *conf)
 {
        int ret;
-       const char *default_devpts_mntopts = "gid=5,newinstance,ptmxmode=0666,mode=0620";
+       char **opts;
        char devpts_mntopts[256];
+       char *mntopt_sets[5];
+       char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620";
 
        if (conf->pty_max <= 0) {
                DEBUG("No new devpts instance will be mounted since no pts "
@@ -1639,18 +1649,33 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
                return -1;
        }
 
-       /* mount new devpts instance */
-       ret = mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, devpts_mntopts);
+       /* gid=5 && max= */
+       mntopt_sets[0] = devpts_mntopts;
+
+       /* !gid=5 && max= */
+       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 + STRLITERALLEN("gid=5") + 1;
+
+       /* end */
+       mntopt_sets[4] = NULL;
+
+       for (ret = -1, opts = mntopt_sets; opts && *opts; opts++) {
+               /* mount new devpts instance */
+               ret = mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, *opts);
+               if (ret == 0)
+                       break;
+       }
+
        if (ret < 0) {
-               /* try mounting without gid=5 */
-               ret = mount("devpts", "/dev/pts", "devpts",
-                           MS_NOSUID | MS_NOEXEC, devpts_mntopts + sizeof("gid=5"));
-               if (ret < 0) {
-                       SYSERROR("Failed to mount new devpts instance");
-                       return -1;
-               }
+               SYSERROR("Failed to mount new devpts instance");
+               return -1;
        }
-       DEBUG("Mount new devpts instance with options \"%s\"", devpts_mntopts);
+       DEBUG("Mount new devpts instance with options \"%s\"", *opts);
 
        /* Remove any pre-existing /dev/ptmx file. */
        ret = remove("/dev/ptmx");
@@ -1723,7 +1748,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"))
@@ -1755,10 +1780,10 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
                return -errno;
        }
 
-       ret = fchmod(console->slave, S_IXUSR | S_IXGRP | S_IXOTH);
+       ret = fchmod(console->slave, S_IXUSR | S_IXGRP);
        if (ret < 0) {
                SYSERROR("Failed to set mode \"0%o\" to \"%s\"",
-                        S_IXUSR | S_IXGRP | S_IXOTH, console->name);
+                        S_IXUSR | S_IXGRP, console->name);
                return -errno;
        }
 
@@ -1777,7 +1802,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"))
@@ -1825,10 +1850,10 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
                return -errno;
        }
 
-       ret = fchmod(console->slave, S_IXUSR | S_IXGRP | S_IXOTH);
+       ret = fchmod(console->slave, S_IXUSR | S_IXGRP);
        if (ret < 0) {
                SYSERROR("Failed to set mode \"0%o\" to \"%s\"",
-                        S_IXUSR | S_IXGRP | S_IXOTH, console->name);
+                        S_IXUSR | S_IXGRP, console->name);
                return -errno;
        }
 
@@ -1888,7 +1913,6 @@ 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;
-       char *saveptr = NULL;
        size_t size;
 
        *mntdata = NULL;
@@ -1909,7 +1933,7 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata)
        }
        *data = 0;
 
-       for (; (p = strtok_r(s, ",", &saveptr)); s = NULL)
+       lxc_iterate_parts(p, s, ",")
                parse_mntopt(p, mntflags, &data, size);
 
        if (*data)
@@ -1939,10 +1963,9 @@ static void parse_propagationopt(char *opt, unsigned long *flags)
        }
 }
 
-static int parse_propagationopts(const char *mntopts, unsigned long *pflags)
+int parse_propagationopts(const char *mntopts, unsigned long *pflags)
 {
        char *p, *s;
-       char *saveptr = NULL;
 
        if (!mntopts)
                return 0;
@@ -1954,7 +1977,7 @@ static int parse_propagationopts(const char *mntopts, unsigned long *pflags)
        }
 
        *pflags = 0L;
-       for (; (p = strtok_r(s, ",", &saveptr)); s = NULL)
+       lxc_iterate_parts(p, s, ",")
                parse_propagationopt(p, pflags);
        free(s);
 
@@ -1993,15 +2016,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;
                }
@@ -2235,7 +2258,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
 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.
@@ -2258,7 +2281,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");
@@ -2268,8 +2291,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);
@@ -2287,8 +2310,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);
@@ -2300,7 +2323,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);
@@ -2372,8 +2395,7 @@ static int setup_mount(const struct lxc_conf *conf,
  */
 static const char nesting_helpers[] =
 "proc dev/.lxc/proc proc create=dir,optional\n"
-"sys dev/.lxc/sys sysfs create=dir,optional\n"
-;
+"sys dev/.lxc/sys sysfs create=dir,optional\n";
 
 FILE *make_anonymous_mount_file(struct lxc_list *mount,
                                bool include_nesting_helpers)
@@ -2398,10 +2420,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;
@@ -2420,8 +2438,8 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
 
        if (include_nesting_helpers) {
                ret = lxc_write_nointr(fd, nesting_helpers,
-                                      sizeof(nesting_helpers) - 1);
-               if (ret != sizeof(nesting_helpers) - 1)
+                                      STRARRAYLEN(nesting_helpers));
+               if (ret != STRARRAYLEN(nesting_helpers))
                        goto on_error;
        }
 
@@ -2523,7 +2541,8 @@ static int setup_caps(struct lxc_list *caps)
                        return -1;
                }
 
-               ret = prctl(PR_CAPBSET_DROP, capid, 0, 0, 0);
+               ret = prctl(PR_CAPBSET_DROP, prctl_arg(capid), prctl_arg(0),
+                           prctl_arg(0), prctl_arg(0));
                if (ret < 0) {
                        SYSERROR("Failed to remove %s capability", drop_entry);
                        return -1;
@@ -2572,7 +2591,8 @@ static int dropcaps_except(struct lxc_list *caps)
                if (caplist[i])
                        continue;
 
-               ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+               ret = prctl(PR_CAPBSET_DROP, prctl_arg(i), prctl_arg(0),
+                           prctl_arg(0), prctl_arg(0));
                if (ret < 0) {
                        SYSERROR("Failed to remove capability %d", i);
                        return -1;
@@ -2624,8 +2644,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
        }
@@ -2639,7 +2661,7 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
        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;
@@ -2674,7 +2696,7 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
        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;
@@ -2739,6 +2761,7 @@ struct lxc_conf *lxc_conf_init(void)
                free(new);
                return NULL;
        }
+       new->rootfs.managed = true;
        new->logfd = -1;
        lxc_list_init(&new->cgroup);
        lxc_list_init(&new->cgroup2);
@@ -2782,13 +2805,13 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                     size_t buf_size)
 {
        int fd, ret;
-       char path[MAXPATHLEN];
+       char path[PATH_MAX];
 
        if (geteuid() != 0 && idtype == ID_TYPE_GID) {
                size_t buflen;
 
-               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);
@@ -2798,7 +2821,7 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                }
 
                if (fd >= 0) {
-                       buflen = sizeof("deny\n") - 1;
+                       buflen = STRLITERALLEN("deny\n");
                        errno = 0;
                        ret = lxc_write_nointr(fd, "deny\n", buflen);
                        close(fd);
@@ -2811,9 +2834,9 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                }
        }
 
-       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);
@@ -2893,7 +2916,7 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
         * 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
@@ -2914,7 +2937,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;
@@ -2922,7 +2945,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
         * +
         * strlen(" ") = 1
         * +
-        * LXC_NUMSTRLEN64
+        * INTTYPE_TO_STRLEN(uint32_t)
         * +
         * strlen(" ") = 1
         *
@@ -2930,7 +2953,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
         * LXC_IDMAPLEN bytes available for our the {g,u]id mapping.
         */
        int ret = 0, gidmap = 0, uidmap = 0;
-       char mapbuf[9 + 1 + LXC_NUMSTRLEN64 + 1 + LXC_IDMAPLEN] = {0};
+       char mapbuf[9 + 1 + INTTYPE_TO_STRLEN(uint32_t) + 1 + LXC_IDMAPLEN] = {0};
        bool had_entry = false, use_shadow = false;
        int hostuid, hostgid;
 
@@ -3017,7 +3040,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) {
@@ -3147,7 +3170,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();
@@ -3318,9 +3341,8 @@ void remount_all_slave(void)
                }
        }
 
-#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;
@@ -3442,7 +3464,8 @@ out:
 /* This does the work of remounting / if it is shared, calling the container
  * pre-mount hooks, and mounting the rootfs.
  */
-int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath)
+int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
+                                 const char *lxcpath)
 {
        int ret;
 
@@ -3470,7 +3493,7 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
                return -1;
        }
 
-       ret = lxc_setup_rootfs(conf);
+       ret = lxc_mount_rootfs(conf);
        if (ret < 0) {
                ERROR("Failed to setup rootfs for");
                return -1;
@@ -3482,23 +3505,22 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
 
 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;
                }
@@ -3511,21 +3533,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)
@@ -3534,7 +3546,7 @@ int lxc_setup(struct lxc_handler *handler)
        const char *lxcpath = handler->lxcpath, *name = handler->name;
        struct lxc_conf *lxc_conf = handler->conf;
 
-       ret = do_rootfs_setup(lxc_conf, name, lxcpath);
+       ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath);
        if (ret < 0) {
                ERROR("Failed to setup rootfs");
                return -1;
@@ -3548,6 +3560,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");
@@ -3583,10 +3599,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;
@@ -3654,6 +3666,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) {
@@ -3673,7 +3691,7 @@ int lxc_setup(struct lxc_handler *handler)
                return -1;
        }
 
-       ret = setup_pivot_root(&lxc_conf->rootfs);
+       ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs);
        if (ret < 0) {
                ERROR("Failed to pivot root into rootfs");
                return -1;
@@ -3826,12 +3844,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;
@@ -3839,7 +3857,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;
@@ -3868,10 +3886,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;
 
@@ -3898,8 +3916,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;
 
@@ -3927,8 +3945,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;
 
@@ -4002,8 +4020,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;
 
@@ -4123,6 +4141,7 @@ struct userns_fn_data {
 
 static int run_userns_fn(void *data)
 {
+       int ret;
        char c;
        struct userns_fn_data *d = data;
 
@@ -4132,14 +4151,14 @@ static int run_userns_fn(void *data)
        /* Wait for parent to finish establishing a new mapping in the user
         * namespace we are executing in.
         */
-       if (lxc_read_nointr(d->p[0], &c, 1) != 1)
-               return -1;
-
+       ret = lxc_read_nointr(d->p[0], &c, 1);
        /* Close read end of the pipe. */
        close(d->p[0]);
+       if (ret != 1)
+               return -1;
 
        if (d->fn_name)
-               TRACE("calling function \"%s\"", d->fn_name);
+               TRACE("Calling function \"%s\"", d->fn_name);
 
        /* Call function to run. */
        return d->fn(d->arg);
@@ -4341,7 +4360,7 @@ on_error:
  * - 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
+ * 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,
@@ -4361,7 +4380,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
        if (!idmap)
                return -1;
 
-       ret = pipe(p);
+       ret = pipe2(p, O_CLOEXEC);
        if (ret < 0) {
                SYSERROR("Failed to create pipe");
                return -1;
@@ -4443,7 +4462,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
        if (!conf)
                return -EINVAL;
 
-       ret = pipe(p);
+       ret = pipe2(p, O_CLOEXEC);
        if (ret < 0) {
                SYSERROR("opening pipe");
                return -1;