From 0fd7309137a71c6e7e5811a89d832978b4c4e2d9 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 11 Mar 2018 00:23:41 +0100 Subject: [PATCH] conf: coding style changes Signed-off-by: Christian Brauner --- src/lxc/conf.c | 1379 +++++++++++++++++++++++++----------------------- 1 file changed, 706 insertions(+), 673 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 383504b47..1a2278042 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -114,6 +114,15 @@ lxc_log_define(lxc_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; +#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) @@ -129,10 +138,18 @@ static int pivot_root(const char *new_root, const char *put_old) extern int pivot_root(const char *new_root, const char *put_old); #endif -char *lxchook_names[NUM_LXC_HOOKS] = {"pre-start", "pre-mount", "mount", - "autodev", "start", "stop", - "post-stop", "clone", "destroy", - "start-host"}; +char *lxchook_names[NUM_LXC_HOOKS] = { + "pre-start", + "pre-mount", + "mount", + "autodev", + "start", + "stop", + "post-stop", + "clone", + "destroy", + "start-host" +}; struct mount_opt { char *name; @@ -150,17 +167,6 @@ struct limit_opt { int value; }; -/* - * 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; -#else -struct lxc_conf *current_config; -#endif - static struct mount_opt mount_opt[] = { { "async", 1, MS_SYNCHRONOUS }, { "atime", 1, MS_NOATIME }, @@ -192,68 +198,68 @@ static struct mount_opt mount_opt[] = { }; static struct mount_opt propagation_opt[] = { - { "private", 0, MS_PRIVATE }, - { "shared", 0, MS_SHARED }, - { "slave", 0, MS_SLAVE }, - { "unbindable", 0, MS_UNBINDABLE }, - { "rprivate", 0, MS_PRIVATE|MS_REC }, - { "rshared", 0, MS_SHARED|MS_REC }, - { "rslave", 0, MS_SLAVE|MS_REC }, - { "runbindable", 0, MS_UNBINDABLE|MS_REC }, - { NULL, 0, 0 }, + { "private", 0, MS_PRIVATE }, + { "shared", 0, MS_SHARED }, + { "slave", 0, MS_SLAVE }, + { "unbindable", 0, MS_UNBINDABLE }, + { "rprivate", 0, MS_PRIVATE|MS_REC }, + { "rshared", 0, MS_SHARED|MS_REC }, + { "rslave", 0, MS_SLAVE|MS_REC }, + { "runbindable", 0, MS_UNBINDABLE|MS_REC }, + { NULL, 0, 0 }, }; static struct caps_opt caps_opt[] = { #if HAVE_LIBCAP - { "chown", CAP_CHOWN }, - { "dac_override", CAP_DAC_OVERRIDE }, - { "dac_read_search", CAP_DAC_READ_SEARCH }, - { "fowner", CAP_FOWNER }, - { "fsetid", CAP_FSETID }, - { "kill", CAP_KILL }, - { "setgid", CAP_SETGID }, - { "setuid", CAP_SETUID }, - { "setpcap", CAP_SETPCAP }, - { "linux_immutable", CAP_LINUX_IMMUTABLE }, - { "net_bind_service", CAP_NET_BIND_SERVICE }, - { "net_broadcast", CAP_NET_BROADCAST }, - { "net_admin", CAP_NET_ADMIN }, - { "net_raw", CAP_NET_RAW }, - { "ipc_lock", CAP_IPC_LOCK }, - { "ipc_owner", CAP_IPC_OWNER }, - { "sys_module", CAP_SYS_MODULE }, - { "sys_rawio", CAP_SYS_RAWIO }, - { "sys_chroot", CAP_SYS_CHROOT }, - { "sys_ptrace", CAP_SYS_PTRACE }, - { "sys_pacct", CAP_SYS_PACCT }, - { "sys_admin", CAP_SYS_ADMIN }, - { "sys_boot", CAP_SYS_BOOT }, - { "sys_nice", CAP_SYS_NICE }, - { "sys_resource", CAP_SYS_RESOURCE }, - { "sys_time", CAP_SYS_TIME }, - { "sys_tty_config", CAP_SYS_TTY_CONFIG }, - { "mknod", CAP_MKNOD }, - { "lease", CAP_LEASE }, + { "chown", CAP_CHOWN }, + { "dac_override", CAP_DAC_OVERRIDE }, + { "dac_read_search", CAP_DAC_READ_SEARCH }, + { "fowner", CAP_FOWNER }, + { "fsetid", CAP_FSETID }, + { "kill", CAP_KILL }, + { "setgid", CAP_SETGID }, + { "setuid", CAP_SETUID }, + { "setpcap", CAP_SETPCAP }, + { "linux_immutable", CAP_LINUX_IMMUTABLE }, + { "net_bind_service", CAP_NET_BIND_SERVICE }, + { "net_broadcast", CAP_NET_BROADCAST }, + { "net_admin", CAP_NET_ADMIN }, + { "net_raw", CAP_NET_RAW }, + { "ipc_lock", CAP_IPC_LOCK }, + { "ipc_owner", CAP_IPC_OWNER }, + { "sys_module", CAP_SYS_MODULE }, + { "sys_rawio", CAP_SYS_RAWIO }, + { "sys_chroot", CAP_SYS_CHROOT }, + { "sys_ptrace", CAP_SYS_PTRACE }, + { "sys_pacct", CAP_SYS_PACCT }, + { "sys_admin", CAP_SYS_ADMIN }, + { "sys_boot", CAP_SYS_BOOT }, + { "sys_nice", CAP_SYS_NICE }, + { "sys_resource", CAP_SYS_RESOURCE }, + { "sys_time", CAP_SYS_TIME }, + { "sys_tty_config", CAP_SYS_TTY_CONFIG }, + { "mknod", CAP_MKNOD }, + { "lease", CAP_LEASE }, #ifdef CAP_AUDIT_READ - { "audit_read", CAP_AUDIT_READ }, + { "audit_read", CAP_AUDIT_READ }, #endif #ifdef CAP_AUDIT_WRITE - { "audit_write", CAP_AUDIT_WRITE }, + { "audit_write", CAP_AUDIT_WRITE }, #endif #ifdef CAP_AUDIT_CONTROL - { "audit_control", CAP_AUDIT_CONTROL }, + { "audit_control", CAP_AUDIT_CONTROL }, #endif - { "setfcap", CAP_SETFCAP }, - { "mac_override", CAP_MAC_OVERRIDE }, - { "mac_admin", CAP_MAC_ADMIN }, + { "setfcap", CAP_SETFCAP }, + { "mac_override", CAP_MAC_OVERRIDE }, + { "mac_admin", CAP_MAC_ADMIN }, #ifdef CAP_SYSLOG - { "syslog", CAP_SYSLOG }, + { "syslog", CAP_SYSLOG }, #endif #ifdef CAP_WAKE_ALARM - { "wake_alarm", CAP_WAKE_ALARM }, + { "wake_alarm", CAP_WAKE_ALARM }, #endif #ifdef CAP_BLOCK_SUSPEND - { "block_suspend", CAP_BLOCK_SUSPEND }, + { "block_suspend", CAP_BLOCK_SUSPEND }, #endif #endif }; @@ -311,9 +317,9 @@ static struct limit_opt limit_opt[] = { static int run_buffer(char *buffer) { - struct lxc_popen_FILE *f; - char *output; int ret; + char *output; + struct lxc_popen_FILE *f; f = lxc_popen(buffer); if (!f) { @@ -493,10 +499,10 @@ int run_script(const char *name, const char *section, const char *script, ...) { int ret; char *buffer, *p; - size_t size = 0; va_list ap; + size_t size = 0; - INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", + INFO("Executing script \"%s\" for container \"%s\", config section \"%s\"", script, name, section); va_start(ap, script); @@ -514,26 +520,17 @@ int run_script(const char *name, const char *section, const char *script, ...) return -1; buffer = alloca(size); - if (!buffer) { - ERROR("Failed to allocate memory."); - return -1; - } - ret = snprintf(buffer, size, "exec %s %s %s", script, name, section); - if (ret < 0 || ret >= size) { - ERROR("Script name too long."); + if (ret < 0 || ret >= size) return -1; - } va_start(ap, script); while ((p = va_arg(ap, char *))) { int len = size - ret; int rc; rc = snprintf(buffer + ret, len, " %s", p); - if (rc < 0 || rc >= len) { - ERROR("Script args too long."); + if (rc < 0 || rc >= len) return -1; - } ret += rc; } va_end(ap); @@ -541,8 +538,7 @@ int run_script(const char *name, const char *section, const char *script, ...) return run_buffer(buffer); } -/* - * pin_rootfs +/* pin_rootfs * if rootfs is a directory, then open ${rootfs}/lxc.hold for writing for * the duration of the container run, to prevent the container from marking * the underlying fs readonly on shutdown. unlink the file immediately so @@ -553,10 +549,9 @@ int run_script(const char *name, const char *section, const char *script, ...) */ int pin_rootfs(const char *rootfs) { - char absrootfs[MAXPATHLEN]; - char absrootfspin[MAXPATHLEN]; + int fd, ret; + char absrootfs[MAXPATHLEN], absrootfspin[MAXPATHLEN]; struct stat s; - int ret, fd; if (rootfs == NULL || strlen(rootfs) == 0) return -2; @@ -564,10 +559,12 @@ int pin_rootfs(const char *rootfs) if (!realpath(rootfs, absrootfs)) return -2; - if (access(absrootfs, F_OK)) + ret = access(absrootfs, F_OK); + if (ret != 0) return -1; - if (stat(absrootfs, &s)) + ret = stat(absrootfs, &s); + if (ret < 0) return -1; if (!S_ISDIR(s.st_mode)) @@ -577,21 +574,23 @@ int pin_rootfs(const char *rootfs) if (ret >= MAXPATHLEN) return -1; - fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR); + fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR); if (fd < 0) return fd; + (void)unlink(absrootfspin); + return fd; } -/* - * If we are asking to remount something, make sure that any - * NOEXEC etc are honored. +/* If we are asking to remount something, make sure that any NOEXEC etc are + * honored. */ unsigned long add_required_remount_flags(const char *s, const char *d, unsigned long flags) { #ifdef HAVE_STATVFS + int ret; struct statvfs sb; unsigned long required_flags = 0; @@ -603,7 +602,9 @@ unsigned long add_required_remount_flags(const char *s, const char *d, if (!s) return flags; - if (statvfs(s, &sb) < 0) + + ret = statvfs(s, &sb); + if (ret < 0) return flags; if (sb.f_flag & MS_NOSUID) @@ -623,8 +624,7 @@ unsigned long add_required_remount_flags(const char *s, const char *d, static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler) { - int r; - int i; + int i, r; static struct { int match_mask; int match_flag; @@ -634,83 +634,87 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha unsigned long flags; const char *options; } default_mounts[] = { - /* Read-only bind-mounting... In older kernels, doing that required - * to do one MS_BIND mount and then MS_REMOUNT|MS_RDONLY the same - * one. According to mount(2) manpage, MS_BIND honors MS_RDONLY from - * kernel 2.6.26 onwards. However, this apparently does not work on - * kernel 3.8. Unfortunately, on that very same kernel, doing the - * same trick as above doesn't seem to work either, there one needs - * to ALSO specify MS_BIND for the remount, otherwise the entire - * fs is remounted read-only or the mount fails because it's busy... - * MS_REMOUNT|MS_BIND|MS_RDONLY seems to work for kernels as low as - * 2.6.32... + /* Read-only bind-mounting... In older kernels, doing that + * required to do one MS_BIND mount and then + * MS_REMOUNT|MS_RDONLY the same one. According to mount(2) + * manpage, MS_BIND honors MS_RDONLY from kernel 2.6.26 + * onwards. However, this apparently does not work on kernel + * 3.8. Unfortunately, on that very same kernel, doing the same + * trick as above doesn't seem to work either, there one needs + * to ALSO specify MS_BIND for the remount, otherwise the + * entire fs is remounted read-only or the mount fails because + * it's busy... MS_REMOUNT|MS_BIND|MS_RDONLY seems to work for + * kernels as low as 2.6.32... */ - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, /* proc/tty is used as a temporary placeholder for proc/sys/net which we'll move back in a few steps */ - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys/net", "%r/proc/tty", NULL, MS_BIND, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys", "%r/proc/sys", NULL, MS_BIND, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/tty", "%r/proc/sys/net", NULL, MS_MOVE, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sysrq-trigger", "%r/proc/sysrq-trigger", NULL, MS_BIND, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sysrq-trigger", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, - { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, - { 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 }, - { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys/devices/virtual/net", NULL, MS_REMOUNT|MS_BIND|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL }, - { 0, 0, NULL, NULL, NULL, 0, NULL } + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys/net", "%r/proc/tty", NULL, MS_BIND, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys", "%r/proc/sys", NULL, MS_BIND, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/tty", "%r/proc/sys/net", NULL, MS_MOVE, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sysrq-trigger", "%r/proc/sysrq-trigger", NULL, MS_BIND, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sysrq-trigger", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, + { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, + { 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 }, + { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys/devices/virtual/net", NULL, MS_REMOUNT|MS_BIND|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL }, + { 0, 0, NULL, NULL, NULL, 0, NULL } }; for (i = 0; default_mounts[i].match_mask; i++) { - if ((flags & default_mounts[i].match_mask) == default_mounts[i].match_flag) { - char *source = NULL; - char *destination = NULL; - int saved_errno; - unsigned long mflags; - - if (default_mounts[i].source) { - /* will act like strdup if %r is not present */ - source = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].source); - if (!source) { - SYSERROR("memory allocation error"); - return -1; - } - } - if (!default_mounts[i].destination) { - ERROR("BUG: auto mounts destination %d was NULL", i); - free(source); - return -1; - } + 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; + + if (default_mounts[i].source) { /* 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; - SYSERROR("memory allocation error"); - free(source); - errno = saved_errno; + source = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].source); + if (!source) return -1; - } - mflags = add_required_remount_flags(source, destination, - default_mounts[i].flags); - r = safe_mount(source, destination, default_mounts[i].fstype, mflags, default_mounts[i].options, conf->rootfs.path ? conf->rootfs.mount : NULL); - saved_errno = errno; - if (r < 0 && errno == ENOENT) { - INFO("Mount source or target for %s on %s doesn't exist. Skipping.", source, destination); - r = 0; - } - else if (r < 0) - SYSERROR("error mounting %s on %s flags %lu", source, destination, mflags); + } + if (!default_mounts[i].destination) { + ERROR("BUG: auto mounts destination %d was NULL", i); free(source); - free(destination); - if (r < 0) { - errno = saved_errno; - return -1; - } + 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; + } + + mflags = add_required_remount_flags(source, destination, + default_mounts[i].flags); + r = safe_mount(source, destination, default_mounts[i].fstype, + mflags, default_mounts[i].options, + conf->rootfs.path ? conf->rootfs.mount : NULL); + saved_errno = errno; + if (r < 0 && errno == ENOENT) { + INFO("Mount source or target for \"%s\" on \"%s\" does " + "not exist. Skipping", source, destination); + r = 0; + } else if (r < 0) { + 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; } } @@ -718,14 +722,16 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha int cg_flags; cg_flags = flags & (LXC_AUTO_CGROUP_MASK & ~LXC_AUTO_CGROUP_FORCE); - /* If the type of cgroup mount was not specified, it depends on the - * container's capabilities as to what makes sense: if we have - * CAP_SYS_ADMIN, the read-only part can be remounted read-write - * anyway, so we may as well default to read-write; then the admin - * will not be given a false sense of security. (And if they really - * want mixed r/o r/w, then they can explicitly specify :mixed.) - * OTOH, if the container lacks CAP_SYS_ADMIN, do only default to - * :mixed, because then the container can't remount it read-write. */ + /* If the type of cgroup mount was not specified, it depends on + * the container's capabilities as to what makes sense: if we + * have CAP_SYS_ADMIN, the read-only part can be remounted + * read-write anyway, so we may as well default to read-write; + * then the admin will not be given a false sense of security. + * (And if they really want mixed r/o r/w, then they can + * explicitly specify :mixed.) OTOH, if the container lacks + * CAP_SYS_ADMIN, do only default to :mixed, because then the + * container can't remount it read-write. + */ if (cg_flags == LXC_AUTO_CGROUP_NOSPEC || cg_flags == LXC_AUTO_CGROUP_FULL_NOSPEC) { int has_sys_admin = 0; @@ -739,10 +745,12 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha else cg_flags = has_sys_admin ? LXC_AUTO_CGROUP_FULL_RW : LXC_AUTO_CGROUP_FULL_MIXED; } + if (flags & LXC_AUTO_CGROUP_FORCE) - cg_flags |= LXC_AUTO_CGROUP_FORCE; + cg_flags |= LXC_AUTO_CGROUP_FORCE; + if (!cgroup_mount(conf->rootfs.path ? conf->rootfs.mount : "", handler, cg_flags)) { - SYSERROR("error mounting /sys/fs/cgroup"); + SYSERROR("Failed to mount \"/sys/fs/cgroup\""); return -1; } } @@ -752,15 +760,18 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha static int setup_utsname(struct utsname *utsname) { + int ret; + if (!utsname) return 0; - if (sethostname(utsname->nodename, strlen(utsname->nodename))) { - SYSERROR("failed to set the hostname to '%s'", utsname->nodename); + ret = sethostname(utsname->nodename, strlen(utsname->nodename)); + if (ret < 0) { + SYSERROR("Failed to set the hostname to \"%s\"", utsname->nodename); return -1; } - INFO("'%s' hostname has been setup", utsname->nodename); + INFO("Set hostname to \"%s\"", utsname->nodename); return 0; } @@ -771,44 +782,44 @@ struct dev_symlinks { }; static const struct dev_symlinks dev_symlinks[] = { - {"/proc/self/fd", "fd"}, - {"/proc/self/fd/0", "stdin"}, - {"/proc/self/fd/1", "stdout"}, - {"/proc/self/fd/2", "stderr"}, + { "/proc/self/fd", "fd" }, + { "/proc/self/fd/0", "stdin" }, + { "/proc/self/fd/1", "stdout" }, + { "/proc/self/fd/2", "stderr" }, }; static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs) { + int i, ret; char path[MAXPATHLEN]; - int ret,i; struct stat s; - for (i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) { const struct dev_symlinks *d = &dev_symlinks[i]; - ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->path ? rootfs->mount : "", d->name); + + ret = snprintf(path, sizeof(path), "%s/dev/%s", + rootfs->path ? rootfs->mount : "", d->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; - /* - * Stat the path first. If we don't get an error - * accept it as is and don't try to create it + /* Stat the path first. If we don't get an error accept it as + * is and don't try to create it */ - if (!stat(path, &s)) { + ret = stat(path, &s); + if (ret == 0) continue; - } ret = symlink(d->oldpath, path); - if (ret && errno != EEXIST) { - if ( errno == EROFS ) { - WARN("Warning: Read Only file system while creating %s", path); + if (errno == EROFS) { + WARN("Failed to create \"%s\". Read-only filesystem", path); } else { - SYSERROR("Error creating %s", path); + SYSERROR("Failed to create \"%s\"", path); return -1; } } } + return 0; } @@ -821,15 +832,19 @@ static bool append_ptyname(char **pp, char *name) *pp = malloc(strlen(name) + strlen("container_ttys=") + 1); if (!*pp) return false; + sprintf(*pp, "container_ttys=%s", name); return true; } + p = realloc(*pp, strlen(*pp) + strlen(name) + 2); if (!p) return false; + *pp = p; strcat(p, " "); strcat(p, name); + return true; } @@ -877,7 +892,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) tty->name, path); continue; } - DEBUG("bind mounted \"%s\" onto \"%s\"", tty->name, + DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, path); ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", @@ -928,8 +943,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf) int lxc_allocate_ttys(const char *name, struct lxc_conf *conf) { - struct lxc_tty_info *ttys = &conf->ttys; int i, ret; + struct lxc_tty_info *ttys = &conf->ttys; /* no tty in the configuration */ if (!conf->tty) @@ -945,26 +960,26 @@ int lxc_allocate_ttys(const char *name, struct lxc_conf *conf) ret = openpty(&tty->master, &tty->slave, tty->name, NULL, NULL); if (ret) { - SYSERROR("failed to create pty device number %d", i); + SYSERROR("Failed to create tty %d", i); ttys->nbtty = i; lxc_delete_tty(ttys); return -ENOTTY; } - DEBUG("allocated pty \"%s\" with master fd %d and slave fd %d", + DEBUG("Created tty \"%s\" with master fd %d and slave fd %d", tty->name, tty->master, tty->slave); /* Prevent leaking the file descriptors to the container */ ret = fcntl(tty->master, F_SETFD, FD_CLOEXEC); if (ret < 0) - WARN("failed to set FD_CLOEXEC flag on master fd %d of " - "pty device \"%s\": %s", + WARN("Failed to set FD_CLOEXEC flag on master fd %d of " + "tty device \"%s\": %s", tty->master, tty->name, strerror(errno)); ret = fcntl(tty->slave, F_SETFD, FD_CLOEXEC); if (ret < 0) - WARN("failed to set FD_CLOEXEC flag on slave fd %d of " - "pty device \"%s\": %s", + WARN("Failed to set FD_CLOEXEC flag on slave fd %d of " + "tty device \"%s\": %s", tty->slave, tty->name, strerror(errno)); tty->busy = 0; @@ -972,7 +987,7 @@ int lxc_allocate_ttys(const char *name, struct lxc_conf *conf) ttys->nbtty = conf->tty; - INFO("finished allocating %d pts devices", conf->tty); + INFO("Finished creating %d tty devices", conf->tty); return 0; } @@ -995,12 +1010,12 @@ void lxc_delete_tty(struct lxc_tty_info *ttys) static int lxc_send_ttys_to_parent(struct lxc_handler *handler) { int i; + int ret = -1; struct lxc_conf *conf = handler->conf; struct lxc_tty_info *ttys = &conf->ttys; int sock = handler->data_sock[0]; - int ret = -1; - if (!conf->tty) + if (conf->tty == 0) return 0; for (i = 0; i < conf->tty; i++) { @@ -1014,7 +1029,7 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler) if (ret < 0) break; - TRACE("Send pty \"%s\" with master fd %d and slave fd %d to " + TRACE("Sent ty \"%s\" with master fd %d and slave fd %d to " "parent", tty->name, tty->master, tty->slave); } @@ -1068,62 +1083,70 @@ on_error: static int setup_rootfs_pivot_root(const char *rootfs) { - int oldroot = -1, newroot = -1; + int ret; + int newroot = -1, oldroot = -1; oldroot = open("/", O_DIRECTORY | O_RDONLY); if (oldroot < 0) { - SYSERROR("Error opening old-/ for fchdir"); + SYSERROR("Failed to open old root directory"); return -1; } + newroot = open(rootfs, O_DIRECTORY | O_RDONLY); if (newroot < 0) { - SYSERROR("Error opening new-/ for fchdir"); - goto fail; + SYSERROR("Failed to open new root directory"); + goto on_error; } /* change into new root fs */ - if (fchdir(newroot)) { - SYSERROR("can't chdir to new rootfs '%s'", rootfs); - goto fail; + 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 */ - if (pivot_root(".", ".")) { - SYSERROR("pivot_root syscall failed"); - goto fail; + 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 + /* 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. */ - if (fchdir(oldroot) < 0) { - SYSERROR("Error entering oldroot"); - goto fail; + ret = fchdir(oldroot); + if (ret < 0) { + SYSERROR("Failed to enter old root directory"); + goto on_error; } - if (umount2(".", MNT_DETACH) < 0) { - SYSERROR("Error detaching old root"); - goto fail; + + ret = umount2(".", MNT_DETACH); + if (ret < 0) { + SYSERROR("Failed to detach old root directory"); + goto on_error; } - if (fchdir(newroot) < 0) { - SYSERROR("Error re-entering newroot"); - goto fail; + ret = fchdir(newroot); + if (ret < 0) { + SYSERROR("Failed to re-enter new root directory"); + goto on_error; } close(oldroot); close(newroot); - DEBUG("pivot_root syscall to '%s' successful", rootfs); + DEBUG("pivot_root(\"%s\") successful", rootfs); return 0; -fail: +on_error: if (oldroot != -1) close(oldroot); if (newroot != -1) close(newroot); + return -1; } @@ -1275,22 +1298,25 @@ static int lxc_setup_rootfs(struct lxc_conf *conf) rootfs = &conf->rootfs; if (!rootfs->path) { - if (mount("", "/", NULL, MS_SLAVE | MS_REC, 0)) { - SYSERROR("Failed to make / rslave."); + ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0); + if (ret < 0) { + SYSERROR("Failed to make / rslave"); return -1; } + return 0; } - if (access(rootfs->mount, F_OK)) { - SYSERROR("Failed to access to \"%s\". Check it is present.", + ret = access(rootfs->mount, F_OK); + if (ret != 0) { + SYSERROR("Failed to access to \"%s\". Check it is present", rootfs->mount); return -1; } bdev = storage_init(conf); if (!bdev) { - ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".", + ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); return -1; @@ -1299,13 +1325,13 @@ static int lxc_setup_rootfs(struct lxc_conf *conf) ret = bdev->ops->mount(bdev); storage_put(bdev); if (ret < 0) { - ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".", + ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); return -1; } - DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\".", + DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\"", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); @@ -1314,35 +1340,35 @@ static int lxc_setup_rootfs(struct lxc_conf *conf) int prepare_ramfs_root(char *root) { - char buf[LXC_LINELEN], *p; - char nroot[PATH_MAX]; + int i, ret; + char *p, *p2; + char buf[LXC_LINELEN], nroot[PATH_MAX]; FILE *f; - int i; - char *p2; - if (realpath(root, nroot) == NULL) - return -errno; + if (!realpath(root, nroot)) + return -1; - if (chdir("/") == -1) - return -errno; + ret = chdir("/"); + if (ret < 0) + return -1; - /* - * We could use here MS_MOVE, but in userns this mount is - * locked and can't be moved. + /* We could use here MS_MOVE, but in userns this mount is locked and + * can't be moved. */ - if (mount(root, "/", NULL, MS_REC | MS_BIND, NULL) < 0) { - SYSERROR("Failed to move %s into /", root); - return -errno; + ret = mount(root, "/", NULL, MS_REC | MS_BIND, NULL); + if (ret < 0) { + SYSERROR("Failed to move \"%s\" into \"/\"", root); + return -1; } - if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) < 0) { - SYSERROR("Failed to make . rprivate"); - return -errno; + ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL); + if (ret < 0) { + SYSERROR("Failed to make \"/\" rprivate"); + return -1; } - /* - * The following code cleans up inhereted mounts which are not - * required for CT. + /* The following code cleans up inhereted 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 @@ -1351,7 +1377,7 @@ int prepare_ramfs_root(char *root) * This loop can be skipped if a container uses unserns, because all * inherited mounts are locked and we should live with all this trash. */ - while (1) { + for (;;) { int progress = 0; f = fopen("./proc/self/mountinfo", "r"); @@ -1359,11 +1385,14 @@ int prepare_ramfs_root(char *root) SYSERROR("Unable to open /proc/self/mountinfo"); return -1; } + while (fgets(buf, LXC_LINELEN, f)) { for (p = buf, i=0; p && i < 4; i++) p = strchr(p+1, ' '); + if (!p) continue; + p2 = strchr(p+1, ' '); if (!p2) continue; @@ -1373,27 +1402,33 @@ int prepare_ramfs_root(char *root) if (strcmp(p + 1, "/") == 0) continue; + if (strcmp(p + 1, "/proc") == 0) continue; - if (umount2(p, MNT_DETACH) == 0) + ret = umount2(p, MNT_DETACH); + if (ret == 0) progress++; } + fclose(f); + if (!progress) break; } - /* This also can be skipped if a container uses unserns */ - umount2("./proc", MNT_DETACH); + /* This also can be skipped if a container uses unserns. */ + (void)umount2("./proc", MNT_DETACH); /* It is weird, but chdir("..") moves us in a new root */ - if (chdir("..") == -1) { + ret = chdir(".."); + if (ret < 0) { SYSERROR("Unable to change working directory"); return -1; } - if (chroot(".") == -1) { + ret = chroot("."); + if (ret < 0) { SYSERROR("Unable to chroot"); return -1; } @@ -1403,28 +1438,33 @@ int prepare_ramfs_root(char *root) static int setup_pivot_root(const struct lxc_rootfs *rootfs) { + int ret; + if (!rootfs->path) { - DEBUG("container does not have a rootfs, so not doing pivot root"); + DEBUG("Container does not have a rootfs"); return 0; } if (detect_ramfs_rootfs()) { - DEBUG("detected that container is on ramfs"); - if (prepare_ramfs_root(rootfs->mount)) { - ERROR("failed to prepare minimal ramfs root"); + DEBUG("Detected that container is on ramfs"); + + ret = prepare_ramfs_root(rootfs->mount); + if (ret < 0) { + ERROR("Failed to prepare minimal ramfs root"); return -1; } - DEBUG("prepared ramfs root for container"); + DEBUG("Prepared ramfs root for container"); return 0; } - if (setup_rootfs_pivot_root(rootfs->mount) < 0) { - ERROR("failed to pivot root"); + ret = setup_rootfs_pivot_root(rootfs->mount); + if (ret < 0) { + ERROR("Failed to pivot_root()"); return -1; } - DEBUG("finished pivot root"); + DEBUG("Finished pivot_root()"); return 0; } @@ -1465,7 +1505,7 @@ static int lxc_setup_devpts(struct lxc_conf *conf) char devpts_mntopts[256]; if (conf->pts <= 0) { - DEBUG("no new devpts instance will be mounted since no pts " + DEBUG("No new devpts instance will be mounted since no pts " "devices are requested"); return 0; } @@ -1485,88 +1525,91 @@ static int lxc_setup_devpts(struct lxc_conf *conf) if (!ret) { ret = umount("/dev/pts"); if (ret < 0) { - SYSERROR("failed to unmount old devpts instance"); + SYSERROR("Failed to unmount old devpts instance"); return -1; } - DEBUG("unmounted old /dev/pts instance"); + DEBUG("Unmounted old devpts instance"); } /* Create mountpoint for devpts instance. */ ret = mkdir("/dev/pts", 0755); if (ret < 0 && errno != EEXIST) { - SYSERROR("failed to create the \"/dev/pts\" directory"); + SYSERROR("Failed to create \"/dev/pts\" directory"); return -1; } /* Mount new devpts instance. */ ret = mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, devpts_mntopts); if (ret < 0) { - SYSERROR("failed to mount new devpts instance"); + 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\"", devpts_mntopts); /* Remove any pre-existing /dev/ptmx file. */ ret = access("/dev/ptmx", F_OK); if (!ret) { ret = remove("/dev/ptmx"); if (ret < 0) { - SYSERROR("failed to remove existing \"/dev/ptmx\""); + SYSERROR("Failed to remove existing \"/dev/ptmx\" file"); return -1; } - DEBUG("removed existing \"/dev/ptmx\""); + DEBUG("Removed existing \"/dev/ptmx\" file"); } /* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */ ret = open("/dev/ptmx", O_CREAT, 0666); if (ret < 0) { - SYSERROR("failed to create dummy \"/dev/ptmx\" file as bind mount target"); + SYSERROR("Failed to create dummy \"/dev/ptmx\" file as bind mount target"); return -1; } close(ret); - DEBUG("created dummy \"/dev/ptmx\" file as bind mount target"); + DEBUG("Created dummy \"/dev/ptmx\" file as bind mount target"); /* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */ ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL); if (!ret) { - DEBUG("bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\""); + DEBUG("Bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\""); return 0; } else { /* Fallthrough and try to create a symlink. */ - ERROR("failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\""); + ERROR("Failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\""); } /* Remove the dummy /dev/ptmx file we created above. */ ret = remove("/dev/ptmx"); if (ret < 0) { - SYSERROR("failed to remove existing \"/dev/ptmx\""); + SYSERROR("Failed to remove existing \"/dev/ptmx\""); return -1; } /* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */ ret = symlink("/dev/pts/ptmx", "/dev/ptmx"); if (ret < 0) { - SYSERROR("failed to create symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); + SYSERROR("Failed to create symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\""); return -1; } - DEBUG("created symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); + DEBUG("Created symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\""); return 0; } static int setup_personality(int persona) { - #if HAVE_SYS_PERSONALITY_H + int ret; + +#if HAVE_SYS_PERSONALITY_H if (persona == -1) return 0; - if (personality(persona) < 0) { - SYSERROR("failed to set personality to '0x%x'", persona); + ret = personality(persona); + if (ret < 0) { + SYSERROR("Failed to set personality to \"0x%x\"", persona); return -1; } - INFO("set personality to '0x%x'", persona); - #endif + INFO("Set personality to \"0x%x\"", persona); +#endif return 0; } @@ -1574,8 +1617,8 @@ static int setup_personality(int persona) static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, const struct lxc_terminal *console) { + int fd, ret; char path[MAXPATHLEN]; - int ret, fd; char *rootfs_path = rootfs->path ? rootfs->mount : ""; if (console->path && !strcmp(console->path, "none")) @@ -1613,13 +1656,14 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH); if (ret < 0) { - SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name); + SYSERROR("Failed to set mode \"0%o\" to \"%s\"", + S_IXUSR | S_IXGRP | S_IXOTH, console->name); return -errno; } ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path); if (ret < 0) { - ERROR("Failed to mount '%s' on '%s'", console->name, path); + ERROR("Failed to mount \"%s\" on \"%s\"", console->name, path); return -1; } @@ -1645,7 +1689,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ret = mkdir(path, 0755); if (ret && errno != EEXIST) { - SYSERROR("Failed with errno %d to create %s", errno, path); + SYSERROR("Failed to create \"%s\"", path); return -errno; } DEBUG("Created directory for console and tty devices at \"%s\"", path); @@ -1656,7 +1700,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ret = creat(lxcpath, 0660); if (ret == -1 && errno != EEXIST) { - SYSERROR("Error %d creating %s", errno, lxcpath); + SYSERROR("Failed to create \"%s\"", lxcpath); return -errno; } if (ret >= 0) @@ -1669,7 +1713,7 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, if (file_exists(path)) { ret = lxc_unstack_mountpoint(path, false); if (ret < 0) { - ERROR("Failed to unmount \"%s\": %s", path, strerror(errno)); + ERROR("%s - Failed to unmount \"%s\"", strerror(errno), path); return -ret; } else { DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path); @@ -1688,14 +1732,15 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH); if (ret < 0) { - SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name); + SYSERROR("Failed to set mode \"0%o\" to \"%s\"", + S_IXUSR | S_IXGRP | S_IXOTH, console->name); return -errno; } /* bind mount console->name to '/dev//console' */ ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); if (ret < 0) { - ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath); + ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); return -1; } DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); @@ -1703,13 +1748,12 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, /* bind mount '/dev//console' to '/dev/console' */ ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path); if (ret < 0) { - ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath); + ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); return -1; } DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); DEBUG("Console has been setup under \"%s\" and mounted to \"%s\"", lxcpath, path); - return 0; } @@ -1731,7 +1775,7 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data) * Otherwise append it to data. */ for (mo = &mount_opt[0]; mo->name != NULL; mo++) { - if (!strncmp(opt, mo->name, strlen(mo->name))) { + if (strncmp(opt, mo->name, strlen(mo->name)) == 0) { if (mo->clear) *flags &= ~mo->flag; else @@ -1745,11 +1789,10 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data) strcat(*data, opt); } -int parse_mntopts(const char *mntopts, unsigned long *mntflags, - char **mntdata) +int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) { - char *s, *data; - char *p, *saveptr = NULL; + char *data, *p, *s; + char *saveptr = NULL; *mntdata = NULL; *mntflags = 0L; @@ -1758,21 +1801,17 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags, return 0; s = strdup(mntopts); - if (!s) { - SYSERROR("failed to allocate memory"); + if (!s) return -1; - } data = malloc(strlen(s) + 1); if (!data) { - SYSERROR("failed to allocate memory"); free(s); return -1; } *data = 0; - for (p = strtok_r(s, ",", &saveptr); p != NULL; - p = strtok_r(NULL, ",", &saveptr)) + for (; (p = strtok_r(s, ",", &saveptr)); s = NULL) parse_mntopt(p, mntflags, &data); if (*data) @@ -1789,23 +1828,23 @@ static void parse_propagationopt(char *opt, unsigned long *flags) struct mount_opt *mo; /* If opt is found in propagation_opt, set or clear flags. */ - for (mo = &propagation_opt[0]; mo->name != NULL; mo++) { - if (strncmp(opt, mo->name, strlen(mo->name)) == 0) { - if (mo->clear) - *flags &= ~mo->flag; - else - *flags |= mo->flag; - return; - } + if (strncmp(opt, mo->name, strlen(mo->name)) != 0) + continue; + + if (mo->clear) + *flags &= ~mo->flag; + else + *flags |= mo->flag; + + return; } } static int parse_propagationopts(const char *mntopts, unsigned long *pflags) { - char *s; - char *p, *saveptr = NULL; - *pflags = 0L; + char *p, *s; + char *saveptr = NULL; if (!mntopts) return 0; @@ -1816,11 +1855,11 @@ static int parse_propagationopts(const char *mntopts, unsigned long *pflags) return -ENOMEM; } - for (p = strtok_r(s, ",", &saveptr); p != NULL; - p = strtok_r(NULL, ",", &saveptr)) + *pflags = 0L; + for (; (p = strtok_r(s, ",", &saveptr)); s = NULL) parse_propagationopt(p, pflags); - free(s); + return 0; } @@ -1831,21 +1870,22 @@ static void null_endofword(char *word) *word = '\0'; } -/* - * skip @nfields spaces in @src - */ +/* skip @nfields spaces in @src */ static char *get_field(char *src, int nfields) { - char *p = src; int i; + char *p = src; for (i = 0; i < nfields; i++) { while (*p && *p != ' ' && *p != '\t') p++; + if (!*p) break; + p++; } + return p; } @@ -1874,8 +1914,9 @@ static int mount_entry(const char *fsname, const char *target, rootfs); if (ret < 0) { if (optional) { - INFO("Failed to mount \"%s\" on \"%s\" (optional): %s", - srcpath ? srcpath : "(null)", target, strerror(errno)); + INFO("%s - Failed to mount \"%s\" on \"%s\" " + "(optional)", strerror(errno), + srcpath ? srcpath : "(null)", target); return 0; } @@ -1974,7 +2015,13 @@ skipremount: static void cull_mntent_opt(struct mntent *mntent) { int i; - char *list[] = {"create=dir", "create=file", "optional", "relative", NULL}; + char *list[] = { + "create=dir", + "create=file", + "optional", + "relative", + NULL + }; for (i = 0; list[i]; i++) { char *p, *p2; @@ -1997,8 +2044,7 @@ static void cull_mntent_opt(struct mntent *mntent) static int mount_entry_create_dir_file(const struct mntent *mntent, const char *path, const struct lxc_rootfs *rootfs, - const char *lxc_name, - const char *lxc_path) + const char *lxc_name, const char *lxc_path) { int fd, ret; char *p1, *p2; @@ -2017,29 +2063,31 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, } } - if (hasmntopt(mntent, "create=file") && access(path, F_OK)) { - int fd; - char *p1, *p2; + if (!hasmntopt(mntent, "create=file")) + return 0; - p1 = strdup(path); - if (!p1) - return -1; + ret = access(path, F_OK); + if (ret == 0) + return 0; - p2 = dirname(p1); + p1 = strdup(path); + if (!p1) + return -1; - ret = mkdir_p(p2, 0755); - free(p1); - if (ret < 0 && errno != EEXIST) { - SYSERROR("Failed to create directory \"%s\"", path); - return -1; - } + p2 = dirname(p1); - fd = open(path, O_CREAT, 0644); - if (fd < 0) - return -1; - close(fd); + ret = mkdir_p(p2, 0755); + free(p1); + if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create directory \"%s\"", path); + return -1; } + fd = open(path, O_CREAT, 0644); + if (fd < 0) + return -1; + close(fd); + return 0; } @@ -2156,98 +2204,26 @@ static int mount_entry_on_relative_rootfs(struct mntent *mntent, const char *lxc_name, const char *lxc_path) { - char path[MAXPATHLEN]; int ret; + char path[MAXPATHLEN]; /* relative to root mount point */ ret = snprintf(path, sizeof(path), "%s/%s", rootfs->mount, mntent->mnt_dir); - if (ret < 0 || ret >= sizeof(path)) { - ERROR("path name too long"); + if (ret < 0 || (size_t)ret >= sizeof(path)) return -1; - } return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path); } -/* This logs a NOTICE() when a user specifies mounts that would conflict with - * devices liblxc sets up automatically. - */ -static void log_notice_on_conflict(const struct lxc_conf *conf, const char *src, - const char *dest) -{ - char *clean_mnt_fsname, *clean_mnt_dir, *tmp; - bool needs_warning = false; - - clean_mnt_fsname = lxc_deslashify(src); - if (!clean_mnt_fsname) - return; - - clean_mnt_dir = lxc_deslashify(dest); - if (!clean_mnt_dir) { - free(clean_mnt_fsname); - return; - } - - tmp = clean_mnt_dir; - if (*tmp == '/') - tmp++; - - if (strncmp(src, "/dev", 4) || strncmp(tmp, "dev", 3)) { - free(clean_mnt_dir); - free(clean_mnt_fsname); - return; - } - - if (!conf->autodev && !conf->pts && !conf->tty && - (!conf->console.path || !strcmp(conf->console.path, "none"))) { - free(clean_mnt_dir); - free(clean_mnt_fsname); - return; - } - - if (!strcmp(tmp, "dev") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/pts") && (conf->autodev > 0 || conf->pts > 0)) - needs_warning = true; - else if (!strcmp(tmp, "dev/ptmx") && (conf->autodev > 0 || conf->pts > 0)) - needs_warning = true; - else if (!strcmp(tmp, "dev/pts/ptmx") && (conf->autodev > 0 || conf->pts > 0)) - needs_warning = true; - else if (!strcmp(tmp, "dev/null") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/zero") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/full") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/urandom") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/random") && conf->autodev > 0) - needs_warning = true; - else if (!strcmp(tmp, "dev/tty") && conf->autodev > 0) - needs_warning = true; - else if (!strncmp(tmp, "dev/tty", 7) && (conf->autodev > 0 || conf->tty > 0)) - needs_warning = true; - - if (needs_warning) - NOTICE("Requesting to mount \"%s\" on \"%s\" while requesting " - "automatic device setup under \"/dev\"", - clean_mnt_fsname, clean_mnt_dir); - - free(clean_mnt_dir); - free(clean_mnt_fsname); -} - 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) { - struct mntent mntent; char buf[4096]; + struct mntent mntent; int ret = -1; while (getmntent_r(file, &mntent, buf, sizeof(buf))) { - log_notice_on_conflict(conf, mntent.mnt_fsname, mntent.mnt_dir); - if (!rootfs->path) ret = mount_entry_on_systemfs(&mntent); else if (mntent.mnt_dir[0] != '/') @@ -2261,7 +2237,7 @@ static int mount_file_entries(const struct lxc_conf *conf, } ret = 0; - INFO("Set up mount entries"); + INFO("Finished setting up mounts"); return ret; } @@ -2294,42 +2270,50 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount) int ret; char *mount_entry; struct lxc_list *iterator; - FILE *f; int fd = -1; - fd = memfd_create("lxc_mount_file", MFD_CLOEXEC); + fd = memfd_create(".lxc_mount_file", MFD_CLOEXEC); if (fd < 0) { if (errno != ENOSYS) return NULL; - f = tmpfile(); + fd = lxc_make_tmpfile((char *){P_tmpdir "/.lxc_mount_file"}, true); + if (fd < 0) { + SYSERROR("Could not create temporary mount file"); + return NULL; + } + TRACE("Created temporary mount file"); - } else { - f = fdopen(fd, "r+"); - TRACE("Created anonymous mount file"); } - - if (!f) { - SYSERROR("Could not create mount file"); - if (fd != -1) - close(fd); + if (fd < 0) { + SYSERROR("Could not create temporary mount file"); return NULL; } - lxc_list_for_each(iterator, mount) { + lxc_list_for_each (iterator, mount) { + size_t len; + mount_entry = iterator->elem; - ret = fprintf(f, "%s\n", mount_entry); - if (ret < strlen(mount_entry)) - WARN("Could not write mount entry to mount file"); - } + len = strlen(mount_entry); - ret = fseek(f, 0, SEEK_SET); - if (ret < 0) { - SYSERROR("Failed to seek mount file"); - fclose(f); - return NULL; + ret = write(fd, mount_entry, len); + if (ret != len) + goto on_error; + + ret = write(fd, "\n", 1); + if (ret != 1) + goto on_error; } - return f; + ret = lseek(fd, 0, SEEK_SET); + if (ret < 0) + goto on_error; + + return fdopen(fd, "r+"); + +on_error: + SYSERROR("Failed to write mount entry to temporary mount file"); + close(fd); + return NULL; } static int setup_mount_entries(const struct lxc_conf *conf, @@ -2337,31 +2321,30 @@ static int setup_mount_entries(const struct lxc_conf *conf, struct lxc_list *mount, const char *lxc_name, const char *lxc_path) { - FILE *f; int ret; + FILE *f; f = make_anonymous_mount_file(mount); if (!f) return -1; ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path); - fclose(f); + return ret; } static int parse_cap(const char *cap) { - char *ptr = NULL; size_t i; int capid = -1; - size_t end = sizeof(caps_opt)/sizeof(caps_opt[0]); + size_t end = sizeof(caps_opt) / sizeof(caps_opt[0]); + char *ptr = NULL; - if (!strcmp(cap, "none")) + if (strcmp(cap, "none") == 0) return -2; for (i = 0; i < end; i++) { - if (strcmp(cap, caps_opt[i].name)) continue; @@ -2370,9 +2353,10 @@ static int parse_cap(const char *cap) } if (capid < 0) { - /* try to see if it's numeric, so the user may specify - * capabilities that the running kernel knows about but - * we don't */ + /* Try to see if it's numeric, so the user may specify + * capabilities that the running kernel knows about but we + * don't + */ errno = 0; capid = strtol(cap, &ptr, 10); if (!ptr || *ptr != '\0' || errno != 0) @@ -2389,10 +2373,10 @@ static int parse_cap(const char *cap) int in_caplist(int cap, struct lxc_list *caps) { - struct lxc_list *iterator; int capid; + struct lxc_list *iterator; - lxc_list_for_each(iterator, caps) { + lxc_list_for_each (iterator, caps) { capid = parse_cap(iterator->elem); if (capid == cap) return 1; @@ -2403,116 +2387,121 @@ int in_caplist(int cap, struct lxc_list *caps) static int setup_caps(struct lxc_list *caps) { - struct lxc_list *iterator; - char *drop_entry; int capid; + char *drop_entry; + struct lxc_list *iterator; - lxc_list_for_each(iterator, caps) { + lxc_list_for_each (iterator, caps) { + int ret; drop_entry = iterator->elem; capid = parse_cap(drop_entry); - - if (capid < 0) { + if (capid < 0) { ERROR("unknown capability %s", drop_entry); return -1; } - DEBUG("drop capability '%s' (%d)", drop_entry, capid); - - if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) { - SYSERROR("failed to remove %s capability", drop_entry); + ret = prctl(PR_CAPBSET_DROP, capid, 0, 0, 0); + if (ret < 0) { + SYSERROR("Failed to remove %s capability", drop_entry); return -1; } - + DEBUG("Dropped %s (%d) capability", drop_entry, capid); } - DEBUG("capabilities have been setup"); - + DEBUG("Capabilities have been setup"); return 0; } static int dropcaps_except(struct lxc_list *caps) { - struct lxc_list *iterator; + int i, capid, numcaps; char *keep_entry; - int i, capid; - int numcaps = lxc_caps_last_cap() + 1; - INFO("found %d capabilities", numcaps); + struct lxc_list *iterator; + numcaps = lxc_caps_last_cap() + 1; if (numcaps <= 0 || numcaps > 200) return -1; + TRACE("Found %d capabilities", numcaps); /* caplist[i] is 1 if we keep capability i */ int *caplist = alloca(numcaps * sizeof(int)); memset(caplist, 0, numcaps * sizeof(int)); - lxc_list_for_each(iterator, caps) { - + lxc_list_for_each (iterator, caps) { keep_entry = iterator->elem; capid = parse_cap(keep_entry); - if (capid == -2) continue; - if (capid < 0) { - ERROR("unknown capability %s", keep_entry); + if (capid < 0) { + ERROR("Unknown capability %s", keep_entry); return -1; } - DEBUG("keep capability '%s' (%d)", keep_entry, capid); - + DEBUG("Keep capability %s (%d)", keep_entry, capid); caplist[capid] = 1; } - for (i=0; ielem; resid = parse_resource(lim->resource); if (resid < 0) { - ERROR("unknown resource %s", lim->resource); + ERROR("Unknown resource %s", lim->resource); return -1; } #if HAVE_PRLIMIT || HAVE_PRLIMIT64 if (prlimit(pid, resid, &lim->limit, NULL) != 0) { - ERROR("failed to set limit %s: %s", lim->resource, strerror(errno)); + ERROR("Failed to set limit %s: %s", lim->resource, + strerror(errno)); return -1; } #else @@ -2520,6 +2509,7 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid) { return -1; #endif } + return 0; } @@ -2527,11 +2517,11 @@ int setup_sysctl_parameters(struct lxc_list *sysctls) { struct lxc_list *it; struct lxc_sysctl *elem; + int ret = 0; char *tmp = NULL; char filename[MAXPATHLEN] = {0}; - int ret = 0; - lxc_list_for_each(it, sysctls) { + lxc_list_for_each (it, sysctls) { elem = it->elem; tmp = lxc_string_replace(".", "/", elem->key); if (!tmp) { @@ -2546,12 +2536,15 @@ int setup_sysctl_parameters(struct lxc_list *sysctls) return -1; } - ret = lxc_write_to_file(filename, elem->value, strlen(elem->value), false); + ret = lxc_write_to_file(filename, elem->value, + strlen(elem->value), false); if (ret < 0) { - ERROR("Failed to setup sysctl parameters %s to %s", elem->key, elem->value); + ERROR("Failed to setup sysctl parameters %s to %s", + elem->key, elem->value); return -1; } } + return 0; } @@ -2559,11 +2552,11 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid) { struct lxc_list *it; struct lxc_proc *elem; + int ret = 0; char *tmp = NULL; char filename[MAXPATHLEN] = {0}; - int ret = 0; - lxc_list_for_each(it, procs) { + lxc_list_for_each (it, procs) { elem = it->elem; tmp = lxc_string_replace(".", "/", elem->filename); if (!tmp) { @@ -2578,12 +2571,15 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid) return -1; } - ret = lxc_write_to_file(filename, elem->value, strlen(elem->value), false); + ret = lxc_write_to_file(filename, elem->value, + strlen(elem->value), false); if (ret < 0) { - ERROR("Failed to setup proc filesystem %s to %s", elem->filename, elem->value); + ERROR("Failed to setup proc filesystem %s to %s", + elem->filename, elem->value); return -1; } } + return 0; } @@ -2591,14 +2587,12 @@ static char *default_rootfs_mount = LXCROOTFSMOUNT; struct lxc_conf *lxc_conf_init(void) { - struct lxc_conf *new; int i; + struct lxc_conf *new; new = malloc(sizeof(*new)); - if (!new) { - ERROR("lxc_conf_init : %s", strerror(errno)); + if (!new) return NULL; - } memset(new, 0, sizeof(*new)); new->loglevel = LXC_LOG_LEVEL_NOTSET; @@ -2621,7 +2615,6 @@ struct lxc_conf *lxc_conf_init(void) new->nbd_idx = -1; new->rootfs.mount = strdup(default_rootfs_mount); if (!new->rootfs.mount) { - ERROR("lxc_conf_init : %s", strerror(errno)); free(new); return NULL; } @@ -2663,17 +2656,15 @@ struct lxc_conf *lxc_conf_init(void) int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, size_t buf_size) { - char path[MAXPATHLEN]; int fd, ret; + char path[MAXPATHLEN]; if (geteuid() != 0 && idtype == ID_TYPE_GID) { size_t buflen; ret = snprintf(path, MAXPATHLEN, "/proc/%d/setgroups", pid); - if (ret < 0 || ret >= MAXPATHLEN) { - ERROR("Failed to create string"); + if (ret < 0 || ret >= MAXPATHLEN) return -E2BIG; - } fd = open(path, O_WRONLY); if (fd < 0 && errno != ENOENT) { @@ -2686,7 +2677,8 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, errno = 0; ret = lxc_write_nointr(fd, "deny\n", buflen); if (ret != buflen) { - SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid); + SYSERROR("Failed to write \"deny\" to " + "\"/proc/%d/setgroups\"", pid); close(fd); return -1; } @@ -2696,10 +2688,8 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, ret = snprintf(path, MAXPATHLEN, "/proc/%d/%cid_map", pid, idtype == ID_TYPE_UID ? 'u' : 'g'); - if (ret < 0 || ret >= MAXPATHLEN) { - ERROR("Failed to create string"); + if (ret < 0 || ret >= MAXPATHLEN) return -E2BIG; - } fd = open(path, O_WRONLY); if (fd < 0) { @@ -2726,7 +2716,6 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, * @return 0 if binary exists but is lacking privilege * @return -ENOENT if binary does not exist * @return -EINVAL if cap to check is neither CAP_SETUID nor CAP_SETGID - * */ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) { @@ -2750,18 +2739,18 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) /* Check if the binary is setuid. */ if (st.st_mode & S_ISUID) { - DEBUG("The binary \"%s\" does have the setuid bit set.", path); + DEBUG("The binary \"%s\" does have the setuid bit set", path); fret = 1; goto cleanup; } - #if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES +#if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES /* Check if it has the CAP_SETUID capability. */ if ((cap & CAP_SETUID) && lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) && 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); + "and CAP_PERMITTED sets", path); fret = 1; goto cleanup; } @@ -2771,19 +2760,19 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) && 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); + "and CAP_PERMITTED sets", path); fret = 1; goto cleanup; } - #else +#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 " - "missing. Manual intervention needed."); + "missing. Manual intervention needed"); fret = 1; - #endif +#endif cleanup: free(path); @@ -2798,13 +2787,13 @@ int lxc_map_ids_exec_wrapper(void *args) int lxc_map_ids(struct lxc_list *idmap, pid_t pid) { - struct id_map *map; - struct lxc_list *iterator; - enum idtype type; + int fill, left; char u_or_g; char *pos; - int fill, left; char cmd_output[MAXPATHLEN]; + struct id_map *map; + struct lxc_list *iterator; + enum idtype type; /* strlen("new@idmap") = 9 * + * strlen(" ") = 1 @@ -2816,9 +2805,9 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) * We add some additional space to make sure that we really have * 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}; - int ret = 0, uidmap = 0, gidmap = 0; - bool use_shadow = false, had_entry = false; + bool had_entry = false, use_shadow = false; /* If new{g,u}idmap exists, that is, if shadow is handing out subuid * ranges, then insist that root also reserve ranges in subuid. This @@ -2838,7 +2827,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) WARN("newgidmap is lacking necessary privileges"); if (uidmap > 0 && gidmap > 0) { - DEBUG("Functional newuidmap and newgidmap binary found."); + DEBUG("Functional newuidmap and newgidmap binary found"); use_shadow = true; } else { /* In case unprivileged users run application containers via @@ -2847,7 +2836,7 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) * doing so by requiring geteuid() == 0. */ DEBUG("No newuidmap and newgidmap binary found. Trying to " - "write directly with euid %d.", geteuid()); + "write directly with euid %d", geteuid()); } for (type = ID_TYPE_UID, u_or_g = 'u'; type <= ID_TYPE_GID; @@ -2910,24 +2899,22 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) return 0; } -/* - * return the host uid/gid to which the container root is mapped in - * *val. +/* Return the host uid/gid to which the container root is mapped in val. * Return true if id was found, false otherwise. */ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, unsigned long *val) { - struct lxc_list *it; - struct id_map *map; unsigned nsid; + struct id_map *map; + struct lxc_list *it; if (idtype == ID_TYPE_UID) nsid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid; else nsid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid; - lxc_list_for_each(it, &conf->id_map) { + lxc_list_for_each (it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; @@ -2942,33 +2929,39 @@ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype) { - struct lxc_list *it; struct id_map *map; - lxc_list_for_each(it, &conf->id_map) { + struct lxc_list *it; + + lxc_list_for_each (it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; + if (id >= map->hostid && id < map->hostid + map->range) return (id - map->hostid) + map->nsid; } + return -1; } int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype) { - struct lxc_list *it; struct id_map *map; + struct lxc_list *it; unsigned int freeid = 0; + again: - lxc_list_for_each(it, &conf->id_map) { + lxc_list_for_each (it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; + if (freeid >= map->nsid && freeid < map->nsid + map->range) { freeid = map->nsid + map->range; goto again; } } + return freeid; } @@ -2978,8 +2971,7 @@ int chown_mapped_root_exec_wrapper(void *args) return -1; } -/* - * chown_mapped_root: for an unprivileged user with uid/gid X to +/* chown_mapped_root: for an unprivileged user with uid/gid X to * chown a dir to subuid/subgid Y, he needs to run chown as root * in a userns where nsid 0 is mapped to hostuid/hostgid Y, and * nsid Y is mapped to hostuid/hostgid X. That way, the container @@ -3019,6 +3011,7 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) return -1; } rootuid = (uid_t)val; + if (!get_mapped_rootid(conf, ID_TYPE_GID, &val)) { ERROR("No gid mapping for container root"); return -1; @@ -3030,6 +3023,7 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) ERROR("Error chowning %s", path); return -1; } + return 0; } @@ -3125,7 +3119,7 @@ int lxc_create_tmp_proc_mount(struct lxc_conf *conf) mounted = lxc_mount_proc_if_needed(conf->rootfs.path ? conf->rootfs.mount : ""); if (mounted == -1) { - SYSERROR("failed to mount /proc in the container"); + SYSERROR("Failed to mount proc in the container"); /* continue only if there is no rootfs */ if (conf->rootfs.path) return -1; @@ -3138,39 +3132,47 @@ int lxc_create_tmp_proc_mount(struct lxc_conf *conf) void tmp_proc_unmount(struct lxc_conf *lxc_conf) { - if (lxc_conf->tmp_umount_proc == 1) { - umount("/proc"); - lxc_conf->tmp_umount_proc = 0; - } + if (lxc_conf->tmp_umount_proc != 1) + return; + + umount("/proc"); + lxc_conf->tmp_umount_proc = 0; } +/* Walk /proc/mounts and change any shared entries to slave. */ void remount_all_slave(void) { - /* walk /proc/mounts and change any shared entries to slave */ - FILE *f = fopen("/proc/self/mountinfo", "r"); - char *line = NULL; + FILE *f; size_t len = 0; + char *line = NULL; + f = fopen("/proc/self/mountinfo", "r"); if (!f) { - SYSERROR("Failed to open /proc/self/mountinfo to mark all shared"); + SYSERROR("Failed to open \"/proc/self/mountinfo\" to mark all shared"); ERROR("Continuing container startup..."); return; } while (getline(&line, &len, f) != -1) { - char *target, *opts; + int ret; + char *opts, *target; + target = get_field(line, 4); if (!target) continue; + opts = get_field(target, 2); if (!opts) continue; + null_endofword(opts); if (!strstr(opts, "shared")) continue; + null_endofword(target); - if (mount(NULL, target, NULL, MS_SLAVE, NULL)) { - SYSERROR("Failed to make %s rslave", target); + ret = mount(NULL, target, NULL, MS_SLAVE, NULL); + if (ret < 0) { + SYSERROR("Failed to make \"%s\" MS_SLAVE", target); ERROR("Continuing..."); } } @@ -3191,24 +3193,22 @@ static int lxc_execute_bind_init(struct lxc_conf *conf) } ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static"); - if (ret < 0 || ret >= PATH_MAX) { - ERROR("Path name too long searching for lxc.init.static"); + if (ret < 0 || ret >= PATH_MAX) return -1; - } if (!file_exists(path)) { - ERROR("%s does not exist on host", path); + ERROR("The file \"%s\" does not exist on host", path); return -1; } ret = snprintf(destpath, PATH_MAX, "%s%s", conf->rootfs.mount, "/init.lxc.static"); - if (ret < 0 || ret >= PATH_MAX) { - ERROR("Path name too long for container's lxc.init.static"); + if (ret < 0 || ret >= PATH_MAX) return -1; - } if (!file_exists(destpath)) { - FILE *pathfile = fopen(destpath, "wb"); + FILE *pathfile; + + pathfile = fopen(destpath, "wb"); if (!pathfile) { SYSERROR("Failed to create mount target \"%s\"", destpath); return -1; @@ -3219,7 +3219,7 @@ static int lxc_execute_bind_init(struct lxc_conf *conf) ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount); if (ret < 0) { - SYSERROR("Failed to bind lxc.init.static into container"); + SYSERROR("Failed to bind mount lxc.init.static into container"); return -1; } @@ -3227,34 +3227,40 @@ static int lxc_execute_bind_init(struct lxc_conf *conf) return 0; } -/* - * This does the work of remounting / if it is shared, calling the - * container pre-mount hooks, and mounting the rootfs. +/* 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 ret; + if (conf->rootfs_setup) { - /* - * rootfs was set up in another namespace. bind-mount it - * to give us a mount in our own ns so we can pivot_root to it - */ const char *path = conf->rootfs.mount; - if (mount(path, path, "rootfs", MS_BIND, NULL) < 0) { - ERROR("Failed to bind-mount container / onto itself"); + + /* The rootfs was set up in another namespace. bind-mount it to + * give us a mount in our own ns so we can pivot_root to it + */ + ret = mount(path, path, "rootfs", MS_BIND, NULL); + if (ret < 0) { + ERROR("Failed to bind mount container / onto itself"); return -1; } + + TRACE("Bind mounted container / onto itself"); return 0; } remount_all_slave(); - if (run_lxc_hooks(name, "pre-mount", conf, NULL)) { - ERROR("failed to run pre-mount hooks for container '%s'.", name); + ret = run_lxc_hooks(name, "pre-mount", conf, NULL); + if (ret < 0) { + ERROR("Failed to run pre-mount hooks"); return -1; } - if (lxc_setup_rootfs(conf)) { - ERROR("failed to setup rootfs for '%s'", name); + ret = lxc_setup_rootfs(conf); + if (ret < 0) { + ERROR("Failed to setup rootfs for"); return -1; } @@ -3264,23 +3270,27 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath static bool verify_start_hooks(struct lxc_conf *conf) { - struct lxc_list *it; char path[MAXPATHLEN]; - lxc_list_for_each(it, &conf->hooks[LXCHOOK_START]) { - char *hookname = it->elem; - struct stat st; + 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", - conf->rootfs.path ? conf->rootfs.mount : "", hookname); + conf->rootfs.path ? conf->rootfs.mount : "", + hookname); if (ret < 0 || ret >= MAXPATHLEN) return false; + ret = stat(path, &st); - if (ret) { + if (ret < 0) { SYSERROR("Start hook %s not found in container", - hookname); + hookname); return false; } + return true; } @@ -3290,9 +3300,8 @@ static bool verify_start_hooks(struct lxc_conf *conf) int lxc_setup(struct lxc_handler *handler) { int ret; - const char *name = handler->name; + const char *lxcpath = handler->lxcpath, *name = handler->name; struct lxc_conf *lxc_conf = handler->conf; - const char *lxcpath = handler->lxcpath; ret = do_rootfs_setup(lxc_conf, name, lxcpath); if (ret < 0) { @@ -3303,7 +3312,7 @@ int lxc_setup(struct lxc_handler *handler) if (handler->nsfd[LXC_NS_UTS] == -1) { ret = setup_utsname(lxc_conf->utsname); if (ret < 0) { - ERROR("failed to setup the utsname for '%s'", name); + ERROR("Failed to setup the utsname %s", name); return -1; } } @@ -3498,7 +3507,7 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf, else return -1; - lxc_list_for_each(it, &conf->hooks[which]) { + lxc_list_for_each (it, &conf->hooks[which]) { int ret; char *hook = it->elem; @@ -3515,11 +3524,12 @@ int lxc_clear_config_caps(struct lxc_conf *c) { struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &c->caps, next) { + lxc_list_for_each_safe (it, &c->caps, next) { lxc_list_del(it); free(it->elem); free(it); } + return 0; } @@ -3527,7 +3537,7 @@ static int lxc_free_idmap(struct lxc_list *id_map) { struct lxc_list *it, *next; - lxc_list_for_each_safe(it, id_map, next) { + lxc_list_for_each_safe (it, id_map, next) { lxc_list_del(it); free(it->elem); free(it); @@ -3543,13 +3553,14 @@ int lxc_clear_idmaps(struct lxc_conf *c) int lxc_clear_config_keepcaps(struct lxc_conf *c) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &c->keepcaps, next) { + lxc_list_for_each_safe (it, &c->keepcaps, next) { lxc_list_del(it); free(it->elem); free(it); } + return 0; } @@ -3564,12 +3575,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 = sizeof("lxc.cgroup2.") - 1; 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 = sizeof("lxc.cgroup.") - 1; list = &c->cgroup; } else { return -EINVAL; @@ -3582,7 +3593,7 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version) else return -EINVAL; - lxc_list_for_each_safe(it, list, next) { + lxc_list_for_each_safe (it, list, next) { struct lxc_cgroup *cg = it->elem; if (!all && strcmp(cg->subsystem, k) != 0) @@ -3601,8 +3612,8 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version) int lxc_clear_limits(struct lxc_conf *c, const char *key) { struct lxc_list *it, *next; - bool all = false; const char *k = NULL; + bool all = false; if (strcmp(key, "lxc.limit") == 0 || strcmp(key, "lxc.prlimit") == 0) all = true; @@ -3613,10 +3624,12 @@ int lxc_clear_limits(struct lxc_conf *c, const char *key) else return -1; - lxc_list_for_each_safe(it, &c->limits, next) { + lxc_list_for_each_safe (it, &c->limits, next) { struct lxc_limit *lim = it->elem; + if (!all && strcmp(lim->resource, k) != 0) continue; + lxc_list_del(it); free(lim->resource); free(lim); @@ -3629,8 +3642,8 @@ int lxc_clear_limits(struct lxc_conf *c, const char *key) int lxc_clear_sysctls(struct lxc_conf *c, const char *key) { struct lxc_list *it, *next; - bool all = false; const char *k = NULL; + bool all = false; if (strcmp(key, "lxc.sysctl") == 0) all = true; @@ -3639,24 +3652,27 @@ int lxc_clear_sysctls(struct lxc_conf *c, const char *key) else return -1; - lxc_list_for_each_safe(it, &c->sysctls, next) { + lxc_list_for_each_safe (it, &c->sysctls, next) { struct lxc_sysctl *elem = it->elem; + if (!all && strcmp(elem->key, k) != 0) continue; + lxc_list_del(it); free(elem->key); free(elem->value); free(elem); free(it); } + return 0; } int lxc_clear_procs(struct lxc_conf *c, const char *key) { - struct lxc_list *it,*next; - bool all = false; + struct lxc_list *it, *next; const char *k = NULL; + bool all = false; if (strcmp(key, "lxc.proc") == 0) all = true; @@ -3665,10 +3681,12 @@ int lxc_clear_procs(struct lxc_conf *c, const char *key) else return -1; - lxc_list_for_each_safe(it, &c->procs, next) { + lxc_list_for_each_safe (it, &c->procs, next) { struct lxc_proc *proc = it->elem; + if (!all && strcmp(proc->filename, k) != 0) continue; + lxc_list_del(it); free(proc->filename); free(proc->value); @@ -3681,37 +3699,40 @@ int lxc_clear_procs(struct lxc_conf *c, const char *key) int lxc_clear_groups(struct lxc_conf *c) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &c->groups, next) { + lxc_list_for_each_safe (it, &c->groups, next) { lxc_list_del(it); free(it->elem); free(it); } + return 0; } int lxc_clear_environment(struct lxc_conf *c) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &c->environment, next) { + lxc_list_for_each_safe (it, &c->environment, next) { lxc_list_del(it); free(it->elem); free(it); } + return 0; } int lxc_clear_mount_entries(struct lxc_conf *c) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &c->mount_list, next) { + lxc_list_for_each_safe (it, &c->mount_list, next) { lxc_list_del(it); free(it->elem); free(it); } + return 0; } @@ -3723,25 +3744,26 @@ int lxc_clear_automounts(struct lxc_conf *c) int lxc_clear_hooks(struct lxc_conf *c, const char *key) { - struct lxc_list *it,*next; - bool all = false, done = false; - const char *k = NULL; int i; + struct lxc_list *it, *next; + const char *k = NULL; + bool all = false, done = false; 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.", sizeof("lxc.hook.") - 1) == 0) + k = key + sizeof("lxc.hook.") - 1; else return -1; - for (i=0; ihooks[i], next) { + lxc_list_for_each_safe (it, &c->hooks[i], next) { lxc_list_del(it); free(it->elem); free(it); } + done = true; } } @@ -3750,14 +3772,15 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key) ERROR("Invalid hook key: %s", key); return -1; } + return 0; } static inline void lxc_clear_aliens(struct lxc_conf *conf) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &conf->aliens, next) { + lxc_list_for_each_safe (it, &conf->aliens, next) { lxc_list_del(it); free(it->elem); free(it); @@ -3766,9 +3789,9 @@ static inline void lxc_clear_aliens(struct lxc_conf *conf) void lxc_clear_includes(struct lxc_conf *conf) { - struct lxc_list *it,*next; + struct lxc_list *it, *next; - lxc_list_for_each_safe(it, &conf->includes, next) { + lxc_list_for_each_safe (it, &conf->includes, next) { lxc_list_del(it); free(it->elem); free(it); @@ -3779,6 +3802,7 @@ void lxc_conf_free(struct lxc_conf *conf) { if (!conf) return; + if (current_config == conf) current_config = NULL; lxc_terminal_conf_free(&conf->console); @@ -3831,8 +3855,8 @@ struct userns_fn_data { static int run_userns_fn(void *data) { - struct userns_fn_data *d = data; char c; + struct userns_fn_data *d = data; /* Close write end of the pipe. */ close(d->p[1]); @@ -3848,6 +3872,7 @@ static int run_userns_fn(void *data) if (d->fn_name) TRACE("calling function \"%s\"", d->fn_name); + /* Call function to run. */ return d->fn(d->arg); } @@ -3872,11 +3897,11 @@ static struct id_map *mapped_nsid_add(struct lxc_conf *conf, unsigned id, static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf, unsigned id, enum idtype idtype) { - struct lxc_list *it; struct id_map *map; + struct lxc_list *it; struct id_map *retmap = NULL; - lxc_list_for_each(it, &conf->id_map) { + lxc_list_for_each (it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; @@ -3890,11 +3915,11 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf, return retmap; } -/* - * Allocate a new {g,u}id mapping for the given {g,u}id. Re-use an already +/* Allocate a new {g,u}id mapping for the given {g,u}id. Re-use an already * existing one or establish a new one. */ -static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, enum idtype type) +static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, + enum idtype type) { int hostid_mapped; struct id_map *entry = NULL, *tmp = NULL; @@ -4052,11 +4077,11 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, const char *fn_name) { pid_t pid; - struct userns_fn_data d; int p[2]; - char c = '1'; - int ret = -1, status = -1; + struct userns_fn_data d; struct lxc_list *idmap; + int ret = -1, status = -1; + char c = '1'; idmap = get_minimal_idmap(conf); if (!idmap) @@ -4076,7 +4101,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, /* Clone child in new user namespace. */ pid = lxc_raw_clone_cb(run_userns_fn, &d, CLONE_NEWUSER); if (pid < 0) { - ERROR("failed to clone child process in new user namespace"); + ERROR("Failed to clone process in new user namespace"); goto on_error; } @@ -4085,23 +4110,23 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, if (lxc_log_get_level() == LXC_LOG_LEVEL_TRACE || conf->loglevel == LXC_LOG_LEVEL_TRACE) { - struct lxc_list *it; struct id_map *map; + struct lxc_list *it; - lxc_list_for_each(it, idmap) { + lxc_list_for_each (it, idmap) { map = it->elem; TRACE("Establishing %cid mapping for \"%d\" in new " "user namespace: nsuid %lu - hostid %lu - range " - "%lu", (map->idtype == ID_TYPE_UID) ? 'u' : 'g', - pid, map->nsid, map->hostid, map->range); + "%lu", + (map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid, + map->nsid, map->hostid, map->range); } } /* Set up {g,u}id mapping for user namespace of child process. */ ret = lxc_map_ids(idmap, pid); if (ret < 0) { - ERROR("Error setting up {g,u}id mappings for child process " - "\"%d\"", pid); + ERROR("Error setting up {g,u}id mappings for child process \"%d\"", pid); goto on_error; } @@ -4131,12 +4156,12 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, { pid_t pid; uid_t euid, egid; - struct userns_fn_data d; int p[2]; struct id_map *map; struct lxc_list *cur; - char c = '1'; + struct userns_fn_data d; int ret = -1; + char c = '1'; 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; @@ -4155,7 +4180,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, /* Clone child in new user namespace. */ pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER); if (pid < 0) { - ERROR("failed to clone child process in new user namespace"); + ERROR("Failed to clone process in new user namespace"); goto on_error; } @@ -4172,7 +4197,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, lxc_list_init(idmap); /* Find container root. */ - lxc_list_for_each(cur, &conf->id_map) { + lxc_list_for_each (cur, &conf->id_map) { struct id_map *tmpmap; tmplist = malloc(sizeof(*tmplist)); @@ -4262,7 +4287,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, if (lxc_log_get_level() == LXC_LOG_LEVEL_TRACE || conf->loglevel == LXC_LOG_LEVEL_TRACE) { - lxc_list_for_each(cur, idmap) { + lxc_list_for_each (cur, idmap) { map = cur->elem; TRACE("establishing %cid mapping for \"%d\" in new " "user namespace: nsuid %lu - hostid %lu - range " @@ -4275,14 +4300,13 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, /* Set up {g,u}id mapping for user namespace of child process. */ ret = lxc_map_ids(idmap, pid); if (ret < 0) { - ERROR("error setting up {g,u}id mappings for child process " - "\"%d\"", pid); + ERROR("error setting up {g,u}id mappings for child process \"%d\"", pid); goto on_error; } /* Tell child to proceed. */ if (write(p[1], &c, 1) != 1) { - SYSERROR("failed telling child process \"%d\" to proceed", pid); + SYSERROR("Failed telling child process \"%d\" to proceed", pid); goto on_error; } @@ -4306,7 +4330,7 @@ on_error: } /* not thread-safe, do not use from api without first forking */ -static char* getuname(void) +static char *getuname(void) { struct passwd *result; @@ -4332,16 +4356,18 @@ static char *getgname(void) /* not thread-safe, do not use from api without first forking */ void suggest_default_idmap(void) { + char *uname, *gname; FILE *f; unsigned int uid = 0, urange = 0, gid = 0, grange = 0; - char *line = NULL; - char *uname, *gname; size_t len = 0; + char *line = NULL; - if (!(uname = getuname())) + uname = getuname(); + if (!uname) return; - if (!(gname = getgname())) { + gname = getgname(); + if (!gname) { free(uname); return; } @@ -4353,17 +4379,22 @@ void suggest_default_idmap(void) free(uname); return; } + while (getline(&line, &len, f) != -1) { + char *p, *p2; size_t no_newline = 0; - char *p = strchr(line, ':'), *p2; + + p = strchr(line, ':'); if (*line == '#') continue; if (!p) continue; *p = '\0'; p++; + if (strcmp(line, uname)) continue; + p2 = strchr(p, ':'); if (!p2) continue; @@ -4375,9 +4406,9 @@ void suggest_default_idmap(void) p2[no_newline] = '\0'; if (lxc_safe_uint(p, &uid) < 0) - WARN("Could not parse UID."); + WARN("Could not parse UID"); if (lxc_safe_uint(p2, &urange) < 0) - WARN("Could not parse UID range."); + WARN("Could not parse UID range"); } fclose(f); @@ -4388,17 +4419,22 @@ void suggest_default_idmap(void) free(uname); return; } + while (getline(&line, &len, f) != -1) { + char *p, *p2; size_t no_newline = 0; - char *p = strchr(line, ':'), *p2; + + p = strchr(line, ':'); if (*line == '#') continue; if (!p) continue; *p = '\0'; p++; + if (strcmp(line, uname)) continue; + p2 = strchr(p, ':'); if (!p2) continue; @@ -4410,9 +4446,9 @@ void suggest_default_idmap(void) p2[no_newline] = '\0'; if (lxc_safe_uint(p, &gid) < 0) - WARN("Could not parse GID."); + WARN("Could not parse GID"); if (lxc_safe_uint(p2, &grange) < 0) - WARN("Could not parse GID range."); + WARN("Could not parse GID range"); } fclose(f); @@ -4439,48 +4475,45 @@ static void free_cgroup_settings(struct lxc_list *result) { struct lxc_list *iterator, *next; - lxc_list_for_each_safe(iterator, result, next) { + lxc_list_for_each_safe (iterator, result, next) { lxc_list_del(iterator); free(iterator); } free(result); } -/* - * Return the list of cgroup_settings sorted according to the following rules +/* Return the list of cgroup_settings sorted according to the following rules * 1. Put memory.limit_in_bytes before memory.memsw.limit_in_bytes */ -struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings) +struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings) { struct lxc_list *result; - struct lxc_list *memsw_limit = NULL; - struct lxc_list *it = NULL; struct lxc_cgroup *cg = NULL; - struct lxc_list *item = NULL; + struct lxc_list *it = NULL, *item = NULL, *memsw_limit = NULL; result = malloc(sizeof(*result)); - if (!result) { - ERROR("failed to allocate memory to sort cgroup settings"); + if (!result) return NULL; - } lxc_list_init(result); - /*Iterate over the cgroup settings and copy them to the output list*/ - lxc_list_for_each(it, cgroup_settings) { + /* Iterate over the cgroup settings and copy them to the output list. */ + lxc_list_for_each (it, cgroup_settings) { item = malloc(sizeof(*item)); if (!item) { - ERROR("failed to allocate memory to sort cgroup settings"); free_cgroup_settings(result); return NULL; } + item->elem = it->elem; cg = it->elem; if (strcmp(cg->subsystem, "memory.memsw.limit_in_bytes") == 0) { /* Store the memsw_limit location */ memsw_limit = item; - } else if (strcmp(cg->subsystem, "memory.limit_in_bytes") == 0 && memsw_limit != NULL) { - /* lxc.cgroup.memory.memsw.limit_in_bytes is found before - * lxc.cgroup.memory.limit_in_bytes, swap these two items */ + } else if (strcmp(cg->subsystem, "memory.limit_in_bytes") == 0 && + memsw_limit != NULL) { + /* lxc.cgroup.memory.memsw.limit_in_bytes is found + * before lxc.cgroup.memory.limit_in_bytes, swap these + * two items */ item->elem = memsw_limit->elem; memsw_limit->elem = it->elem; } -- 2.47.3