The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/2698
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 24b97297056b3d61b53aa467bbdb32037ff7e0d7 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Wed, 17 Oct 2018 18:36:28 +0200 Subject: [PATCH] parse: protect against config updates during parse Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/parse.c | 81 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/src/lxc/parse.c b/src/lxc/parse.c index 2fdb18ec8..439cc29c3 100644 --- a/src/lxc/parse.c +++ b/src/lxc/parse.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <string.h> #include <sys/mman.h> +#include <sys/sendfile.h> #include "config.h" #include "log.h" @@ -67,32 +68,71 @@ int lxc_strmunmap(void *addr, size_t length) int lxc_file_for_each_line_mmap(const char *file, lxc_file_cb callback, void *data) { - int fd, saved_errno; - char *buf, *line; + int saved_errno; + char *line; struct stat st; - int ret = 0; + ssize_t ret = 0; + int fd = -1, memfd = -1; + char *buf = NULL; + + memfd = memfd_create(".lxc_mount_file", MFD_CLOEXEC); + if (memfd < 0) { + char template[] = P_tmpdir "/.lxc_mountinfo_XXXXXX"; + + if (errno != ENOSYS) { + SYSERROR("Failed to create memory file"); + goto on_error; + } + + TRACE("Failed to create in-memory file. Falling back to " + "temporary file"); + memfd = lxc_make_tmpfile(template, true); + if (memfd < 0) { + SYSERROR("Failed to create temporary file \"%s\"", template); + goto on_error; + } + } fd = open(file, O_RDONLY | O_CLOEXEC); if (fd < 0) { - SYSERROR("Failed to open config file \"%s\"", file); + SYSERROR("Failed to open file \"%s\"", file); return -1; } ret = fstat(fd, &st); if (ret < 0) { - SYSERROR("Failed to stat config file \"%s\"", file); - goto on_error_fstat; + SYSERROR("Failed to stat file \"%s\"", file); + goto on_error; } ret = 0; if (st.st_size == 0) - goto on_error_fstat; + goto on_error; + + /* sendfile() handles up to 2GB. No config file should be that big. */ + ret = sendfile(memfd, fd, NULL, st.st_size); + if (ret < 0) { + SYSERROR("Failed to sendfile \"%s\"", file); + goto on_error; + } - ret = -1; - buf = lxc_strmmap(NULL, st.st_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_POPULATE, fd, 0); + ret = write(memfd, "\0", 1); + if (ret < 0) { + SYSERROR("Failed to append zero byte"); + goto on_error; + } + + ret = lseek(memfd, 0, SEEK_SET); + if (ret < 0) { + SYSERROR("Failed to lseek"); + goto on_error; + } + + buf = mmap(NULL, st.st_size + 1, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, memfd, 0); if (buf == MAP_FAILED) { - SYSERROR("Failed to map config file \"%s\"", file); + buf = NULL; + SYSERROR("Failed to mmap"); goto on_error; } @@ -111,15 +151,18 @@ int lxc_file_for_each_line_mmap(const char *file, lxc_file_cb callback, void *da } on_error: - if (lxc_strmunmap(buf, st.st_size) < 0) { - SYSERROR("Failed to unmap config file \"%s\"", file); - if (ret == 0) - ret = -1; - } - -on_error_fstat: saved_errno = errno; - close(fd); + if (fd >= 0) + close(fd); + if (memfd >= 0) + close(memfd); + if (buf) { + if (munmap(buf, st.st_size + 1) < 0) { + SYSERROR("Failed to unmap"); + if (ret == 0) + ret = -1; + } + } errno = saved_errno; return ret;
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel