diff --git a/lxc-1.0.7-defines.patch b/lxc-1.0.7-defines.patch deleted file mode 100644 index bd0276b..0000000 --- a/lxc-1.0.7-defines.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up lxc-1.0.7/src/lxc/utils.c.orig lxc-1.0.7/src/lxc/utils.c ---- lxc-1.0.7/src/lxc/utils.c.orig 2014-12-05 21:50:20.000000000 +0100 -+++ lxc-1.0.7/src/lxc/utils.c 2015-10-24 22:32:32.763132507 +0200 -@@ -44,6 +44,14 @@ - #include "log.h" - #include "lxclock.h" - -+#ifndef O_PATH -+#define O_PATH 010000000 -+#endif -+ -+#ifndef O_NOFOLLOW -+#define O_NOFOLLOW 00400000 -+#endif -+ - lxc_log_define(lxc_utils, lxc); - - static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) diff --git a/lxc-1.0.7-fix-CVE-2015-1331.patch b/lxc-1.0.7-fix-CVE-2015-1331.patch deleted file mode 100644 index 6e19dca..0000000 --- a/lxc-1.0.7-fix-CVE-2015-1331.patch +++ /dev/null @@ -1,104 +0,0 @@ -From a5d9627f29233df421c62f38ace9aefbf6e401b5 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 3 Jul 2015 09:26:17 -0500 -Subject: [PATCH 1/2] CVE-2015-1331: lxclock: use /run/lxc/lock rather than - /run/lock/lxc -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This prevents an unprivileged user to use LXC to create arbitrary file -on the filesystem. - -Signed-off-by: Serge Hallyn -Signed-off-by: Tyler Hicks -Acked-by: Stéphane Graber ---- - src/lxc/lxclock.c | 38 ++++++++++---------------------------- - src/tests/locktests.c | 2 +- - 2 files changed, 11 insertions(+), 29 deletions(-) - -diff --git a/src/lxc/lxclock.c b/src/lxc/lxclock.c -index 0cd09be..92fbb50 100644 ---- a/src/lxc/lxclock.c -+++ b/src/lxc/lxclock.c -@@ -103,13 +103,13 @@ static char *lxclock_name(const char *p, const char *n) - char *rundir; - - /* lockfile will be: -- * "/run" + "/lock/lxc/$lxcpath/$lxcname + '\0' if root -+ * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root - * or -- * $XDG_RUNTIME_DIR + "/lock/lxc/$lxcpath/$lxcname + '\0' if non-root -+ * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root - */ - -- /* length of "/lock/lxc/" + $lxcpath + "/" + $lxcname + '\0' */ -- len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 2; -+ /* length of "/lxc/lock/" + $lxcpath + "/" + $lxcname + '\0' */ -+ len = strlen("/lxc/lock/") + strlen(n) + strlen(p) + 2; - rundir = get_rundir(); - if (!rundir) - return NULL; -@@ -120,7 +120,7 @@ static char *lxclock_name(const char *p, const char *n) - return NULL; - } - -- ret = snprintf(dest, len, "%s/lock/lxc/%s", rundir, p); -+ ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p); - if (ret < 0 || ret >= len) { - free(dest); - free(rundir); -@@ -128,31 +128,13 @@ static char *lxclock_name(const char *p, const char *n) - } - ret = mkdir_p(dest, 0755); - if (ret < 0) { -- /* fall back to "/tmp/" $(id -u) "/lxc/" $lxcpath / $lxcname + '\0' */ -- int l2 = 33 + strlen(n) + strlen(p); -- if (l2 > len) { -- char *d; -- d = realloc(dest, l2); -- if (!d) { -- free(dest); -- free(rundir); -- return NULL; -- } -- len = l2; -- dest = d; -- } -- ret = snprintf(dest, len, "/tmp/%d/lxc/%s", geteuid(), p); -- if (ret < 0 || ret >= len) { -- free(dest); -- free(rundir); -- return NULL; -- } -- ret = snprintf(dest, len, "/tmp/%d/lxc/%s/%s", geteuid(), p, n); -- } else -- ret = snprintf(dest, len, "%s/lock/lxc/%s/%s", rundir, p, n); -+ free(dest); -+ free(rundir); -+ return NULL; -+ } - -+ ret = snprintf(dest, len, "%s/lxc/lock/%s/%s", rundir, p, n); - free(rundir); -- - if (ret < 0 || ret >= len) { - free(dest); - return NULL; -diff --git a/src/tests/locktests.c b/src/tests/locktests.c -index dd3393a..233ca12 100644 ---- a/src/tests/locktests.c -+++ b/src/tests/locktests.c -@@ -122,7 +122,7 @@ int main(int argc, char *argv[]) - exit(1); - } - struct stat sb; -- char *pathname = RUNTIME_PATH "/lock/lxc/var/lib/lxc/"; -+ char *pathname = RUNTIME_PATH "/lxc/lock/var/lib/lxc/"; - ret = stat(pathname, &sb); - if (ret != 0) { - fprintf(stderr, "%d: filename %s not created\n", __LINE__, --- -2.4.3 - diff --git a/lxc-1.0.7-fix-CVE-2015-1334.patch b/lxc-1.0.7-fix-CVE-2015-1334.patch deleted file mode 100644 index 22e8c03..0000000 --- a/lxc-1.0.7-fix-CVE-2015-1334.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 3f2fc8f458b54c3d327708ba853fe8f445da7c0c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?St=C3=A9phane=20Graber?= -Date: Thu, 16 Jul 2015 16:37:51 -0400 -Subject: [PATCH 2/2] CVE-2015-1334: Don't use the container's /proc during - attach -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A user could otherwise over-mount /proc and prevent the apparmor profile -or selinux label from being written which combined with a modified -/bin/sh or other commonly used binary would lead to unconfined code -execution. - -Reported-by: Roman Fiedler -Signed-off-by: Stéphane Graber ---- - src/lxc/attach.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 93 insertions(+), 4 deletions(-) - -diff --git a/src/lxc/attach.c b/src/lxc/attach.c -index ed6ea8d..16d942c 100644 ---- a/src/lxc/attach.c -+++ b/src/lxc/attach.c -@@ -76,6 +76,82 @@ - - lxc_log_define(lxc_attach, lxc); - -+int lsm_set_label_at(int procfd, int on_exec, char* lsm_label) { -+ int labelfd = -1; -+ int ret = 0; -+ const char* name; -+ char* command = NULL; -+ -+ name = lsm_name(); -+ -+ if (strcmp(name, "nop") == 0) -+ goto out; -+ -+ if (strcmp(name, "none") == 0) -+ goto out; -+ -+ /* We don't support on-exec with AppArmor */ -+ if (strcmp(name, "AppArmor") == 0) -+ on_exec = 0; -+ -+ if (on_exec) { -+ labelfd = openat(procfd, "self/attr/exec", O_RDWR); -+ } -+ else { -+ labelfd = openat(procfd, "self/attr/current", O_RDWR); -+ } -+ -+ if (labelfd < 0) { -+ SYSERROR("Unable to open LSM label"); -+ ret = -1; -+ goto out; -+ } -+ -+ if (strcmp(name, "AppArmor") == 0) { -+ int size; -+ -+ command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1); -+ if (!command) { -+ SYSERROR("Failed to write apparmor profile"); -+ ret = -1; -+ goto out; -+ } -+ -+ size = sprintf(command, "changeprofile %s", lsm_label); -+ if (size < 0) { -+ SYSERROR("Failed to write apparmor profile"); -+ ret = -1; -+ goto out; -+ } -+ -+ if (write(labelfd, command, size + 1) < 0) { -+ SYSERROR("Unable to set LSM label"); -+ ret = -1; -+ goto out; -+ } -+ } -+ else if (strcmp(name, "SELinux") == 0) { -+ if (write(labelfd, lsm_label, strlen(lsm_label) + 1) < 0) { -+ SYSERROR("Unable to set LSM label"); -+ ret = -1; -+ goto out; -+ } -+ } -+ else { -+ ERROR("Unable to restore label for unknown LSM: %s", name); -+ ret = -1; -+ goto out; -+ } -+ -+out: -+ free(command); -+ -+ if (labelfd != -1) -+ close(labelfd); -+ -+ return ret; -+} -+ - static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) - { - struct lxc_proc_context_info *info = calloc(1, sizeof(*info)); -@@ -573,6 +649,7 @@ struct attach_clone_payload { - struct lxc_proc_context_info* init_ctx; - lxc_attach_exec_t exec_function; - void* exec_payload; -+ int procfd; - }; - - static int attach_child_main(void* data); -@@ -625,6 +702,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun - char* cwd; - char* new_cwd; - int ipc_sockets[2]; -+ int procfd; - signed long personality; - - if (!options) -@@ -836,6 +914,13 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun - rexit(-1); - } - -+ procfd = open("/proc", O_DIRECTORY | O_RDONLY); -+ if (procfd < 0) { -+ SYSERROR("Unable to open /proc"); -+ shutdown(ipc_sockets[1], SHUT_RDWR); -+ rexit(-1); -+ } -+ - /* attach now, create another subprocess later, since pid namespaces - * only really affect the children of the current process - */ -@@ -863,7 +948,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun - .options = options, - .init_ctx = init_ctx, - .exec_function = exec_function, -- .exec_payload = exec_payload -+ .exec_payload = exec_payload, -+ .procfd = procfd - }; - /* We use clone_parent here to make this subprocess a direct child of - * the initial process. Then this intermediate process can exit and -@@ -901,6 +987,7 @@ static int attach_child_main(void* data) - { - struct attach_clone_payload* payload = (struct attach_clone_payload*)data; - int ipc_socket = payload->ipc_socket; -+ int procfd = payload->procfd; - lxc_attach_options_t* options = payload->options; - struct lxc_proc_context_info* init_ctx = payload->init_ctx; - #if HAVE_SYS_PERSONALITY_H -@@ -1026,12 +1113,11 @@ static int attach_child_main(void* data) - close(ipc_socket); - - /* set new apparmor profile/selinux context */ -- if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM)) { -+ if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) { - int on_exec; - - on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; -- ret = lsm_process_label_set(init_ctx->lsm_label, 0, on_exec); -- if (ret < 0) { -+ if (lsm_set_label_at(procfd, on_exec, init_ctx->lsm_label) < 0) { - rexit(-1); - } - } -@@ -1082,6 +1168,9 @@ static int attach_child_main(void* data) - } - } - -+ /* we don't need proc anymore */ -+ close(procfd); -+ - /* we're done, so we can now do whatever the user intended us to do */ - rexit(payload->exec_function(payload->exec_payload)); - } --- -2.4.3 - diff --git a/lxc-1.0.7-fix-CVE-2015-1335.patch b/lxc-1.0.7-fix-CVE-2015-1335.patch deleted file mode 100644 index 158778c..0000000 --- a/lxc-1.0.7-fix-CVE-2015-1335.patch +++ /dev/null @@ -1,621 +0,0 @@ -From 557d4b31a797603bed52ccc23a2ad11fe2bce910 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Mon, 31 Aug 2015 12:57:20 -0500 -Subject: [PATCH 1/1] Protect container mounts against symlinks - -When a container starts up, lxc sets up the container's inital fstree -by doing a bunch of mounting, guided by the container configuration -file. The container config is owned by the admin or user on the host, -so we do not try to guard against bad entries. However, since the -mount target is in the container, it's possible that the container admin -could divert the mount with symbolic links. This could bypass proper -container startup (i.e. confinement of a root-owned container by the -restrictive apparmor policy, by diverting the required write to -/proc/self/attr/current), or bypass the (path-based) apparmor policy -by diverting, say, /proc to /mnt in the container. - -To prevent this, - -1. do not allow mounts to paths containing symbolic links - -2. do not allow bind mounts from relative paths containing symbolic -links. - -Details: - -Define safe_mount which ensures that the container has not inserted any -symbolic links into any mount targets for mounts to be done during -container setup. - -The host's mount path may contain symbolic links. As it is under the -control of the administrator, that's ok. So safe_mount begins the check -for symbolic links after the rootfs->mount, by opening that directory. - -It opens each directory along the path using openat() relative to the -parent directory using O_NOFOLLOW. When the target is reached, it -mounts onto /proc/self/fd/. - -Use safe_mount() in mount_entry(), when mounting container proc, -and when needed. In particular, safe_mount() need not be used in -any case where: - -1. the mount is done in the container's namespace -2. the mount is for the container's rootfs -3. the mount is relative to a tmpfs or proc/sysfs which we have - just safe_mount()ed ourselves - -Since we were using proc/net as a temporary placeholder for /proc/sys/net -during container startup, and proc/net is a symbolic link, use proc/tty -instead. - -Update the lxc.container.conf manpage with details about the new -restrictions. - -Finally, add a testcase to test some symbolic link possibilities. - -Signed-off-by: Serge Hallyn ---- - doc/lxc.container.conf.sgml.in | 12 +++ - src/lxc/cgfs.c | 5 +- - src/lxc/cgmanager.c | 4 +- - src/lxc/conf.c | 30 +++--- - src/lxc/utils.c | 233 +++++++++++++++++++++++++++++++++++++++++ - src/lxc/utils.h | 2 + - src/tests/Makefile.am | 3 +- - src/tests/lxc-test-symlink | 88 ++++++++++++++++ - 8 files changed, 359 insertions(+), 18 deletions(-) - create mode 100644 src/tests/lxc-test-symlink - -diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in -index 9cd0c57..6f06762 100644 ---- a/doc/lxc.container.conf.sgml.in -+++ b/doc/lxc.container.conf.sgml.in -@@ -676,6 +676,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - container. This is useful to mount /etc, /var or /home for - examples. - -+ -+ NOTE - LXC will generally ensure that mount targets and relative -+ bind-mount sources are properly confined under the container -+ root, to avoid attacks involving over-mounting host directories -+ and files. (Symbolic links in absolute mount sources are ignored) -+ However, if the container configuration first mounts a directory which -+ is under the control of the container user, such as /home/joe, into -+ the container at some path, and then mounts -+ under path, then a TOCTTOU attack would be -+ possible where the container user modifies a symbolic link under -+ his home directory at just the right time. -+ - - - -diff --git a/src/lxc/cgfs.c b/src/lxc/cgfs.c -index 15346dc..df4ad46 100644 ---- a/src/lxc/cgfs.c -+++ b/src/lxc/cgfs.c -@@ -1363,7 +1363,10 @@ static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type) - if (!path) - return false; - snprintf(path, bufsz, "%s/sys/fs/cgroup", root); -- r = mount("cgroup_root", path, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME, "size=10240k,mode=755"); -+ r = safe_mount("cgroup_root", path, "tmpfs", -+ MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME, -+ "size=10240k,mode=755", -+ root); - if (r < 0) { - SYSERROR("could not mount tmpfs to /sys/fs/cgroup in the container"); - return false; -diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c -index 1872f03..79af751 100644 ---- a/src/lxc/cgmanager.c -+++ b/src/lxc/cgmanager.c -@@ -1332,7 +1332,7 @@ static bool cgm_bind_dir(const char *root, const char *dirname) - } - - /* mount a tmpfs there so we can create subdirs */ -- if (mount("cgroup", cgpath, "tmpfs", 0, "size=10000,mode=755")) { -+ if (safe_mount("cgroup", cgpath, "tmpfs", 0, "size=10000,mode=755", root)) { - SYSERROR("Failed to mount tmpfs at %s", cgpath); - return false; - } -@@ -1343,7 +1343,7 @@ static bool cgm_bind_dir(const char *root, const char *dirname) - return false; - } - -- if (mount(dirname, cgpath, "none", MS_BIND, 0)) { -+ if (safe_mount(dirname, cgpath, "none", MS_BIND, 0, root)) { - SYSERROR("Failed to bind mount %s to %s", dirname, cgpath); - return false; - } -diff --git a/src/lxc/conf.c b/src/lxc/conf.c -index 320b6c9..8acee5a 100644 ---- a/src/lxc/conf.c -+++ b/src/lxc/conf.c -@@ -795,7 +795,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha - } - mflags = add_required_remount_flags(source, destination, - default_mounts[i].flags); -- r = mount(source, destination, default_mounts[i].fstype, mflags, default_mounts[i].options); -+ 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) - SYSERROR("error mounting %s on %s flags %lu", source, destination, mflags); -@@ -989,7 +989,8 @@ static int setup_tty(const struct lxc_rootfs *rootfs, - return -1; - } - -- if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) { -+ if (safe_mount(pty_info->name, lxcpath, "none", MS_BIND, 0, -+ rootfs->mount)) { - WARN("failed to mount '%s'->'%s'", - pty_info->name, path); - continue; -@@ -1016,7 +1017,8 @@ static int setup_tty(const struct lxc_rootfs *rootfs, - close(ret); - } - } -- if (mount(pty_info->name, path, "none", MS_BIND, 0)) { -+ if (safe_mount(pty_info->name, path, "none", MS_BIND, 0, -+ rootfs->mount)) { - WARN("failed to mount '%s'->'%s'", - pty_info->name, path); - continue; -@@ -1442,16 +1444,16 @@ static int mount_autodev(const char *name, char *root, const char *lxcpath) - SYSERROR("WARNING: Failed to create symlink '%s'->'%s'", host_path, devtmpfs_path); - } - DEBUG("Bind mounting %s to %s", devtmpfs_path , path ); -- ret = mount(devtmpfs_path, path, NULL, MS_BIND, 0 ); -+ ret = safe_mount(devtmpfs_path, path, NULL, MS_BIND, 0, root ); - } else { - /* Only mount a tmpfs on here if we don't already a mount */ - if ( ! mount_check_fs( host_path, NULL ) ) { - DEBUG("Mounting tmpfs to %s", host_path ); -- ret = mount("none", path, "tmpfs", 0, "size=100000,mode=755"); -+ ret = safe_mount("none", path, "tmpfs", 0, "size=100000,mode=755", root); - } else { - /* This allows someone to manually set up a mount */ - DEBUG("Bind mounting %s to %s", host_path, path ); -- ret = mount(host_path , path, NULL, MS_BIND, 0 ); -+ ret = safe_mount(host_path , path, NULL, MS_BIND, 0, root ); - } - } - if (ret) { -@@ -1828,7 +1830,7 @@ static int setup_dev_console(const struct lxc_rootfs *rootfs, - return -1; - } - -- if (mount(console->name, path, "none", MS_BIND, 0)) { -+ if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount)) { - ERROR("failed to mount '%s' on '%s'", console->name, path); - return -1; - } -@@ -1883,7 +1885,7 @@ static int setup_ttydir_console(const struct lxc_rootfs *rootfs, - return 0; - } - -- if (mount(console->name, lxcpath, "none", MS_BIND, 0)) { -+ if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs->mount)) { - ERROR("failed to mount '%s' on '%s'", console->name, lxcpath); - return -1; - } -@@ -2033,13 +2035,13 @@ static char *get_field(char *src, int nfields) - - static int mount_entry(const char *fsname, const char *target, - const char *fstype, unsigned long mountflags, -- const char *data, int optional) -+ const char *data, int optional, const char *rootfs) - { - #ifdef HAVE_STATVFS - struct statvfs sb; - #endif - -- if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) { -+ if (safe_mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data, rootfs)) { - if (optional) { - INFO("failed to mount '%s' on '%s' (optional): %s", fsname, - target, strerror(errno)); -@@ -2172,7 +2174,7 @@ static inline int mount_entry_on_systemfs(struct mntent *mntent) - } - - ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir, -- mntent->mnt_type, mntflags, mntdata, optional); -+ mntent->mnt_type, mntflags, mntdata, optional, NULL); - - free(pathdirname); - free(mntdata); -@@ -2259,7 +2261,7 @@ skipabs: - } - - ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, -- mntflags, mntdata, optional); -+ mntflags, mntdata, optional, rootfs->mount); - - free(mntdata); - -@@ -2315,7 +2317,7 @@ static int mount_entry_on_relative_rootfs(struct mntent *mntent, - } - - ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, -- mntflags, mntdata, optional); -+ mntflags, mntdata, optional, rootfs); - - free(pathdirname); - free(mntdata); -@@ -3981,7 +3983,7 @@ static int do_tmp_proc_mount(const char *rootfs) - return 0; - - domount: -- if (mount("proc", path, "proc", 0, NULL)) -+ if (safe_mount("proc", path, "proc", 0, NULL, rootfs)) - return -1; - INFO("Mounted /proc in container for security transition"); - return 1; -diff --git a/src/lxc/utils.c b/src/lxc/utils.c -index 5ef04fc..cfd4092 100644 ---- a/src/lxc/utils.c -+++ b/src/lxc/utils.c -@@ -1322,3 +1322,236 @@ next_loop: - free(path); - return NULL; - } -+ -+/* -+ * @path: a pathname where / replaced with '\0'. -+ * @offsetp: pointer to int showing which path segment was last seen. -+ * Updated on return to reflect the next segment. -+ * @fulllen: full original path length. -+ * Returns a pointer to the next path segment, or NULL if done. -+ */ -+static char *get_nextpath(char *path, int *offsetp, int fulllen) -+{ -+ int offset = *offsetp; -+ -+ if (offset >= fulllen) -+ return NULL; -+ -+ while (path[offset] != '\0' && offset < fulllen) -+ offset++; -+ while (path[offset] == '\0' && offset < fulllen) -+ offset++; -+ -+ *offsetp = offset; -+ return (offset < fulllen) ? &path[offset] : NULL; -+} -+ -+/* -+ * Check that @subdir is a subdir of @dir. @len is the length of -+ * @dir (to avoid having to recalculate it). -+ */ -+static bool is_subdir(const char *subdir, const char *dir, size_t len) -+{ -+ size_t subdirlen = strlen(subdir); -+ -+ if (subdirlen < len) -+ return false; -+ if (strncmp(subdir, dir, len) != 0) -+ return false; -+ if (dir[len-1] == '/') -+ return true; -+ if (subdir[len] == '/' || subdirlen == len) -+ return true; -+ return false; -+} -+ -+/* -+ * Check if the open fd is a symlink. Return -ELOOP if it is. Return -+ * -ENOENT if we couldn't fstat. Return 0 if the fd is ok. -+ */ -+static int check_symlink(int fd) -+{ -+ struct stat sb; -+ int ret = fstat(fd, &sb); -+ if (ret < 0) -+ return -ENOENT; -+ if (S_ISLNK(sb.st_mode)) -+ return -ELOOP; -+ return 0; -+} -+ -+/* -+ * Open a file or directory, provided that it contains no symlinks. -+ * -+ * CAVEAT: This function must not be used for other purposes than container -+ * setup before executing the container's init -+ */ -+static int open_if_safe(int dirfd, const char *nextpath) -+{ -+ int newfd = openat(dirfd, nextpath, O_RDONLY | O_NOFOLLOW); -+ if (newfd >= 0) // was not a symlink, all good -+ return newfd; -+ -+ if (errno == ELOOP) -+ return newfd; -+ -+ if (errno == EPERM || errno == EACCES) { -+ /* we're not root (cause we got EPERM) so -+ try opening with O_PATH */ -+ newfd = openat(dirfd, nextpath, O_PATH | O_NOFOLLOW); -+ if (newfd >= 0) { -+ /* O_PATH will return an fd for symlinks. We know -+ * nextpath wasn't a symlink at last openat, so if fd -+ * is now a link, then something * fishy is going on -+ */ -+ int ret = check_symlink(newfd); -+ if (ret < 0) { -+ close(newfd); -+ newfd = ret; -+ } -+ } -+ } -+ -+ return newfd; -+} -+ -+/* -+ * Open a path intending for mounting, ensuring that the final path -+ * is inside the container's rootfs. -+ * -+ * CAVEAT: This function must not be used for other purposes than container -+ * setup before executing the container's init -+ * -+ * @target: path to be opened -+ * @prefix_skip: a part of @target in which to ignore symbolic links. This -+ * would be the container's rootfs. -+ * -+ * Return an open fd for the path, or <0 on error. -+ */ -+static int open_without_symlink(const char *target, const char *prefix_skip) -+{ -+ int curlen = 0, dirfd, fulllen, i; -+ char *dup = NULL; -+ -+ fulllen = strlen(target); -+ -+ /* make sure prefix-skip makes sense */ -+ if (prefix_skip) { -+ curlen = strlen(prefix_skip); -+ if (!is_subdir(target, prefix_skip, curlen)) { -+ ERROR("WHOA there - target '%s' didn't start with prefix '%s'", -+ target, prefix_skip); -+ return -EINVAL; -+ } -+ /* -+ * get_nextpath() expects the curlen argument to be -+ * on a (turned into \0) / or before it, so decrement -+ * curlen to make sure that happens -+ */ -+ if (curlen) -+ curlen--; -+ } else { -+ prefix_skip = "/"; -+ curlen = 0; -+ } -+ -+ /* Make a copy of target which we can hack up, and tokenize it */ -+ if ((dup = strdup(target)) == NULL) { -+ SYSERROR("Out of memory checking for symbolic link"); -+ return -ENOMEM; -+ } -+ for (i = 0; i < fulllen; i++) { -+ if (dup[i] == '/') -+ dup[i] = '\0'; -+ } -+ -+ dirfd = open(prefix_skip, O_RDONLY); -+ if (dirfd < 0) -+ goto out; -+ while (1) { -+ int newfd, saved_errno; -+ char *nextpath; -+ -+ if ((nextpath = get_nextpath(dup, &curlen, fulllen)) == NULL) -+ goto out; -+ newfd = open_if_safe(dirfd, nextpath); -+ saved_errno = errno; -+ close(dirfd); -+ dirfd = newfd; -+ if (newfd < 0) { -+ errno = saved_errno; -+ if (errno == ELOOP) -+ SYSERROR("%s in %s was a symbolic link!", nextpath, target); -+ else -+ SYSERROR("Error examining %s in %s", nextpath, target); -+ goto out; -+ } -+ } -+ -+out: -+ free(dup); -+ return dirfd; -+} -+ -+/* -+ * Safely mount a path into a container, ensuring that the mount target -+ * is under the container's @rootfs. (If @rootfs is NULL, then the container -+ * uses the host's /) -+ * -+ * CAVEAT: This function must not be used for other purposes than container -+ * setup before executing the container's init -+ */ -+int safe_mount(const char *src, const char *dest, const char *fstype, -+ unsigned long flags, const void *data, const char *rootfs) -+{ -+ int srcfd = -1, destfd, ret, saved_errno; -+ char srcbuf[50], destbuf[50]; // only needs enough for /proc/self/fd/ -+ const char *mntsrc = src; -+ -+ if (!rootfs) -+ rootfs = ""; -+ -+ /* todo - allow symlinks for relative paths if 'allowsymlinks' option is passed */ -+ if (flags & MS_BIND && src && src[0] != '/') { -+ INFO("this is a relative bind mount"); -+ srcfd = open_without_symlink(src, NULL); -+ if (srcfd < 0) -+ return srcfd; -+ ret = snprintf(srcbuf, 50, "/proc/self/fd/%d", srcfd); -+ if (ret < 0 || ret > 50) { -+ close(srcfd); -+ ERROR("Out of memory"); -+ return -EINVAL; -+ } -+ mntsrc = srcbuf; -+ } -+ -+ destfd = open_without_symlink(dest, rootfs); -+ if (destfd < 0) { -+ if (srcfd != -1) -+ close(srcfd); -+ return destfd; -+ } -+ -+ ret = snprintf(destbuf, 50, "/proc/self/fd/%d", destfd); -+ if (ret < 0 || ret > 50) { -+ if (srcfd != -1) -+ close(srcfd); -+ close(destfd); -+ ERROR("Out of memory"); -+ return -EINVAL; -+ } -+ -+ ret = mount(mntsrc, destbuf, fstype, flags, data); -+ saved_errno = errno; -+ if (srcfd != -1) -+ close(srcfd); -+ close(destfd); -+ if (ret < 0) { -+ errno = saved_errno; -+ SYSERROR("Failed to mount %s onto %s", src, dest); -+ return ret; -+ } -+ -+ return 0; -+} -diff --git a/src/lxc/utils.h b/src/lxc/utils.h -index f48f403..30e8a98 100644 ---- a/src/lxc/utils.h -+++ b/src/lxc/utils.h -@@ -280,3 +280,5 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval); - int detect_shared_rootfs(void); - int detect_ramfs_rootfs(void); - char *on_path(char *cmd); -+int safe_mount(const char *src, const char *dest, const char *fstype, -+ unsigned long flags, const void *data, const char *rootfs); -diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am -index 19a4205..edb62d6 100644 ---- a/src/tests/Makefile.am -+++ b/src/tests/Makefile.am -@@ -48,7 +48,7 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \ - lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove \ - lxc-test-apparmor - --bin_SCRIPTS = lxc-test-autostart -+bin_SCRIPTS = lxc-test-autostart lxc-test-symlink - - if DISTRO_UBUNTU - bin_SCRIPTS += lxc-test-usernic lxc-test-ubuntu lxc-test-unpriv -@@ -71,6 +71,7 @@ EXTRA_DIST = \ - locktests.c \ - lxcpath.c \ - lxc-test-autostart \ -+ lxc-test-symlink \ - lxc-test-ubuntu \ - lxc-test-unpriv \ - may_control.c \ -diff --git a/src/tests/lxc-test-symlink b/src/tests/lxc-test-symlink -new file mode 100644 -index 0000000..37320f0 ---- /dev/null -+++ b/src/tests/lxc-test-symlink -@@ -0,0 +1,88 @@ -+#!/bin/bash -+ -+set -ex -+ -+# lxc: linux Container library -+ -+# Authors: -+# Serge Hallyn -+# -+# This is a regression test for symbolic links -+ -+dirname=`mktemp -d` -+fname=`mktemp` -+fname2=`mktemp` -+ -+lxcpath=/var/lib/lxcsym1 -+ -+cleanup() { -+ lxc-destroy -P $lxcpath -f -n symtest1 || true -+ rm -f $lxcpath -+ rmdir $dirname || true -+ rm -f $fname || true -+ rm -f $fname2 || true -+} -+ -+trap cleanup EXIT SIGHUP SIGINT SIGTERM -+ -+testrun() { -+ expected=$1 -+ run=$2 -+ pass="pass" -+ lxc-start -P $lxcpath -n symtest1 -l trace -o $lxcpath/log || pass="fail" -+ [ $pass = "pass" ] && lxc-wait -P $lxcpath -n symtest1 -t 10 -s RUNNING || pass="fail" -+ if [ "$pass" != "$expected" ]; then -+ echo "Test $run: expected $expected but container did not. Start log:" -+ cat $lxcpath/log -+ echo "FAIL: Test $run: expected $expected but container did not." -+ false -+ fi -+ lxc-stop -P $lxcpath -n symtest1 -k || true -+} -+ -+# make lxcpath a symlink - this should NOT cause failure -+ln -s /var/lib/lxc $lxcpath -+ -+lxc-destroy -P $lxcpath -f -n symtest1 || true -+lxc-create -P $lxcpath -t busybox -n symtest1 -+ -+cat >> /var/lib/lxc/symtest1/config << EOF -+lxc.mount.entry = $dirname opt/xxx/dir none bind,create=dir -+lxc.mount.entry = $fname opt/xxx/file none bind,create=file -+lxc.mount.entry = $fname2 opt/xxx/file2 none bind -+EOF -+ -+# Regular - should succeed -+mkdir -p /var/lib/lxc/symtest1/rootfs/opt/xxx -+touch /var/lib/lxc/symtest1/rootfs/opt/xxx/file2 -+testrun pass 1 -+ -+# symlink - should fail -+rm -rf /var/lib/lxc/symtest1/rootfs/opt/xxx -+mkdir -p /var/lib/lxc/symtest1/rootfs/opt/xxx2 -+ln -s /var/lib/lxc/symtest1/rootfs/opt/xxx2 /var/lib/lxc/symtest1/rootfs/opt/xxx -+touch /var/lib/lxc/symtest1/rootfs/opt/xxx/file2 -+testrun fail 2 -+ -+# final final symlink - should fail -+rm -rf $lxcpath/symtest1/rootfs/opt/xxx -+mkdir -p $lxcpath/symtest1/rootfs/opt/xxx -+mkdir -p $lxcpath/symtest1/rootfs/opt/xxx/dir -+touch $lxcpath/symtest1/rootfs/opt/xxx/file -+touch $lxcpath/symtest1/rootfs/opt/xxx/file2src -+ln -s $lxcpath/symtest1/rootfs/opt/xxx/file2src $lxcpath/symtest1/rootfs/opt/xxx/file2 -+testrun fail 3 -+ -+# Ideally we'd also try a loop device, but that won't work in nested containers -+# anyway - TODO -+ -+# what about /proc itself -+ -+rm -rf $lxcpath/symtest1/rootfs/opt/xxx -+mkdir -p $lxcpath/symtest1/rootfs/opt/xxx -+touch $lxcpath/symtest1/rootfs/opt/xxx/file2 -+mv $lxcpath/symtest1/rootfs/proc $lxcpath/symtest1/rootfs/proc1 -+ln -s $lxcpath/symtest1/rootfs/proc1 $lxcpath/symtest1/rootfs/proc -+testrun fail 4 -+ -+echo "all tests passed" --- -2.5.0 - diff --git a/lxc-1.0.7-fix-lxc-top-crash.patch b/lxc-1.0.7-fix-lxc-top-crash.patch deleted file mode 100644 index 088551c..0000000 --- a/lxc-1.0.7-fix-lxc-top-crash.patch +++ /dev/null @@ -1,34 +0,0 @@ -From c21cf4cdbf277157fd54af9c762fd42af5434abd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?St=C3=A9phane=20Graber?= -Date: Mon, 26 Jan 2015 00:11:55 -0500 -Subject: [PATCH] lua: fix crash on missing blkio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Closes: #403 - -Signed-off-by: Dwight Engen -Acked-by: Stéphane Graber ---- - src/lua-lxc/lxc.lua | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lua-lxc/lxc.lua b/src/lua-lxc/lxc.lua -index 44e4bf1..72a1531 100755 ---- a/src/lua-lxc/lxc.lua -+++ b/src/lua-lxc/lxc.lua -@@ -271,6 +271,10 @@ function container:stat_match_get_int(item, match, column) - local val - local lines = self:get_cgroup_item(item) - -+ if (lines == nil) then -+ return 0 -+ end -+ - for line in lines:gmatch("[^\r\n]+") do - if (string.find(line, match)) then - local col --- -2.4.3 - diff --git a/lxc-1.0.7-kmsg.patch b/lxc-1.0.7-kmsg.patch deleted file mode 100644 index 2320e45..0000000 --- a/lxc-1.0.7-kmsg.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e8a1665479c979e74950cb2b07568636c8290561 Mon Sep 17 00:00:00 2001 -From: Michael Adam -Date: Fri, 2 Jan 2015 21:12:21 +0100 -Subject: [PATCH] lxc-fedora: when using systemd, set lxc.kmsg = 0 in the - config - -This is to prevent systemd-journald to enter a 100% cpu loop. - -Signed-off-by: Michael Adam -Acked-by: Serge E. Hallyn ---- - templates/lxc-fedora.in | 21 +++++++++++++++------ - 1 file changed, 15 insertions(+), 6 deletions(-) - -diff --git a/templates/lxc-fedora.in b/templates/lxc-fedora.in -index f2aab42..76bec44 100644 ---- a/templates/lxc-fedora.in -+++ b/templates/lxc-fedora.in -@@ -1073,13 +1073,22 @@ lxc.include = @LXCTEMPLATECONFIG@/fedora.common.conf - " >> $config_path/config - fi - -+ if [ "x$have_systemd" = "x1" ]; then -+ cat <> $config_path/config -+lxc.autodev = 1 -+lxc.kmsg = 0 -+EOF -+ else -+ cat <> $config_path/config -+lxc.autodev = 0 -+EOF -+ fi -+ - # Append things which require expansion here... - cat <> $config_path/config - lxc.arch = $arch - lxc.utsname = $utsname - --lxc.autodev = $auto_dev -- - # When using LXC with apparmor, uncomment the next line to run unconfined: - #lxc.aa_profile = unconfined - -@@ -1293,12 +1302,12 @@ if [ -z "$release" ]; then - fi - fi - --# Fedora 15 and above run systemd. We need autodev enabled to keep -+# Fedora 15 and above run systemd.We need autodev enabled to keep - # systemd from causing problems. -+# Also, kmsg must not be mapped to prevent a 100% cpu loop -+# in systemd-journald. - if [ $release -gt 14 ]; then -- auto_dev="1" --else -- auto_dev="0" -+ have_systemd="1" - fi - - if [ "$(id -u)" != "0" ]; then --- -2.4.3 - diff --git a/lxc-1.0.7-overlayfs-name.patch b/lxc-1.0.7-overlayfs-name.patch deleted file mode 100644 index 48747db..0000000 --- a/lxc-1.0.7-overlayfs-name.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 388db0d9ebf1b24c538a68813077b7ace31db68f Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Mon, 26 Jan 2015 05:58:50 +0000 -Subject: [PATCH] Use 'overlay' as fs name when needed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Close #389 - -We will probably also want to switch the order of the mount attempts, as -the new overlay fs should quickly become the more common scenario. - -Signed-off-by: Serge Hallyn -Acked-by: KATOH Yasufumi -Acked-by: Stéphane Graber ---- - src/lxc/bdev.c | 29 +++++++++++++++++++++++++++-- - 1 file changed, 27 insertions(+), 2 deletions(-) - -diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c -index 7eae8df..d29a386 100644 ---- a/src/lxc/bdev.c -+++ b/src/lxc/bdev.c -@@ -2147,6 +2147,28 @@ static int overlayfs_detect(const char *path) - return 0; - } - -+static char *overlayfs_name; -+static char *detect_overlayfs_name(void) -+{ -+ char *v = "overlayfs"; -+ char *line = NULL; -+ size_t len = 0; -+ FILE *f = fopen("/proc/filesystems", "r"); -+ if (!f) -+ return v; -+ -+ while (getline(&line, &len, f) != -1) { -+ if (strcmp(line, "nodev\toverlay\n") == 0) { -+ v = "overlay"; -+ break; -+ } -+ } -+ -+ fclose(f); -+ free(line); -+ return v; -+} -+ - // - // XXXXXXX plain directory bind mount ops - // -@@ -2165,6 +2187,9 @@ static int overlayfs_mount(struct bdev *bdev) - if (!bdev->src || !bdev->dest) - return -22; - -+ if (!overlayfs_name) -+ overlayfs_name = detect_overlayfs_name(); -+ - // separately mount it first - // mount -t overlayfs -oupperdir=${upper},lowerdir=${lower} lower dest - dup = alloca(strlen(bdev->src)+1); -@@ -2225,13 +2250,13 @@ static int overlayfs_mount(struct bdev *bdev) - } - - // mount without workdir option for overlayfs before v21 -- ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options); -+ ret = mount(lower, bdev->dest, overlayfs_name, MS_MGC_VAL | mntflags, options); - if (ret < 0) { - INFO("overlayfs: error mounting %s onto %s options %s. retry with workdir", - lower, bdev->dest, options); - - // retry with workdir option for overlayfs v22 and higher -- ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options_work); -+ ret = mount(lower, bdev->dest, overlayfs_name, MS_MGC_VAL | mntflags, options_work); - if (ret < 0) - SYSERROR("overlayfs: error mounting %s onto %s options %s", - lower, bdev->dest, options_work); --- -2.4.3 - diff --git a/lxc-1.0.8-lxc-create-doc.patch b/lxc-1.0.8-lxc-create-doc.patch new file mode 100644 index 0000000..dfc81fb --- /dev/null +++ b/lxc-1.0.8-lxc-create-doc.patch @@ -0,0 +1,44 @@ +From 729084d3d7e238bc12d16d503da480e808b6d858 Mon Sep 17 00:00:00 2001 +From: KATOH Yasufumi +Date: Wed, 26 Nov 2014 16:20:54 +0900 +Subject: [PATCH] doc: change "-t" option of lxc-create(1) to being required + +* fix "reg" to "req" in English (fix for commit b8683fe) +* change "opt" to "req" in Japanese + +Signed-off-by: KATOH Yasufumi +Acked-by: Serge E. Hallyn +--- + doc/ja/lxc-create.sgml.in | 2 +- + doc/lxc-create.sgml.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/doc/ja/lxc-create.sgml.in b/doc/ja/lxc-create.sgml.in +index 63eedc4..c7834d3 100644 +--- a/doc/ja/lxc-create.sgml.in ++++ b/doc/ja/lxc-create.sgml.in +@@ -57,7 +57,7 @@ by KATOH Yasufumi + lxc-create + -n name + -f config_file +- -t template ++ -t template + -B backingstore + -- template-options + +diff --git a/doc/lxc-create.sgml.in b/doc/lxc-create.sgml.in +index 053fa0f..3339bf3 100644 +--- a/doc/lxc-create.sgml.in ++++ b/doc/lxc-create.sgml.in +@@ -51,7 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + lxc-create + -n name + -f config_file +- -t template ++ -t template + -B backingstore + -- template-options + +-- +2.4.3 + diff --git a/lxc.spec b/lxc.spec index 53f24d5..b4ba4d8 100644 --- a/lxc.spec +++ b/lxc.spec @@ -21,30 +21,18 @@ %global luapkgdir %{_datadir}/lua/%{luaver} Name: lxc -Version: 1.0.7 -Release: 4%{?dist} +Version: 1.0.8 +Release: 1%{?dist} Summary: Linux Resource Containers Group: Applications/System License: LGPLv2+ and GPLv2 URL: http://linuxcontainers.org Source0: http://linuxcontainers.org/downloads/%{name}-%{version}.tar.gz Patch0: lxc-1.0.4-fix-init.patch -# upstream commit f547349 -Patch2: lxc-1.0.7-fix-CVE-2015-1331.patch -# upstream commit 15ec0fd -Patch3: lxc-1.0.7-fix-CVE-2015-1334.patch -# fix provided by upstream -Patch4: lxc-1.0.7-fix-CVE-2015-1335.patch # similar to rhbz#1263612 -Patch5: lxc-1.0.7-fix-bootorder.patch -# upstream commit 27ec06f9, for building on EPEL6 -Patch6: lxc-1.0.7-defines.patch -# upstream commit c21cf4cd, see rhbz#1152384 -Patch7: lxc-1.0.7-fix-lxc-top-crash.patch -# upstream commit e8a16654, see rhbz#1204389 -Patch8: lxc-1.0.7-kmsg.patch -# upstream commit 388db0d9, see rhbz#1217516 -Patch9: lxc-1.0.7-overlayfs-name.patch +Patch1: lxc-1.0.7-fix-bootorder.patch +# Upstream commit 729084d3, missed 1.0.8 +Patch2: lxc-1.0.8-lxc-create-doc.patch BuildRequires: docbook-utils Buildrequires: docbook2X Buildrequires: doxygen @@ -65,8 +53,6 @@ BuildRequires: systemd # for lxc-top Requires: lua-%{name}%{?_isa} = %{version}-%{release} Requires: lua-alt-getopt -# patch4 changes a Makefile.am -BuildRequires: autoconf automake %{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}-%{version}} @@ -186,16 +172,8 @@ This package contains documentation for %{name}. %prep %setup -q -n %{name}-%{version} %patch0 -p1 +%patch1 -p1 %patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -# patch4 changes a Makefile.am -./autogen.sh %build @@ -381,6 +359,10 @@ fi %changelog +* Sun Nov 15 2015 Thomas Moschny - 1.0.8-1 +- Update to 1.0.8. +- Remove patches applied upstream. + * Sun Oct 25 2015 Thomas Moschny - 1.0.7-4 - Add some patches: - Allow building on EPEL6. diff --git a/sources b/sources index 3dbe193..bc539e9 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -b48f468a9bef0e4e140dd723f0a65ad0 lxc-1.0.7.tar.gz +b6e6bf578dc1133c76d853ef00fdfcf4 lxc-1.0.8.tar.gz