From: Christian Brauner Date: Mon, 4 Jun 2018 10:49:05 +0000 (+0200) Subject: conf: copy mountinfo for remount_all_slave() X-Git-Tag: lxc-3.1.0~270^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2374%2Fhead;p=thirdparty%2Flxc.git conf: copy mountinfo for remount_all_slave() While a container reads mountinfo from proc fs, the mountinfo can be changed by the kernel anytime. This has caused critical issues on some devices. Signed-off-by: Donghwa Jeong dh48.jeong@samsung.com Reported-by: Donghwa Jeong dh48.jeong@samsung.com Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 05d58081e..48cd7f8b3 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -3178,14 +3179,63 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf) /* Walk /proc/mounts and change any shared entries to slave. */ void remount_all_slave(void) { + int memfd, mntinfo_fd, ret; + ssize_t copied; FILE *f; size_t len = 0; char *line = NULL; - f = fopen("/proc/self/mountinfo", "r"); + mntinfo_fd = open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC); + if (mntinfo_fd < 0) + return; + + memfd = memfd_create(".lxc_mountinfo", MFD_CLOEXEC); + if (memfd < 0) { + char template[] = P_tmpdir "/.lxc_mountinfo_XXXXXX"; + + if (errno != ENOSYS) { + close(mntinfo_fd); + WARN("Failed to create temporary in-memory file"); + return; + } + + memfd = lxc_make_tmpfile(template, true); + } + if (memfd < 0) { + close(mntinfo_fd); + WARN("Failed to create temporary file"); + return; + } + +#define __LXC_SENDFILE_MAX 0x7ffff000 /* maximum number of bytes sendfile can handle */ +again: + copied = sendfile(memfd, mntinfo_fd, NULL, __LXC_SENDFILE_MAX); + if (copied < 0) { + if (errno == EINTR) + goto again; + + close(mntinfo_fd); + close(memfd); + WARN("Failed to copy \"/proc/self/mountinfo\""); + return; + } + close(mntinfo_fd); + + /* After a successful fdopen() memfd will be closed when calling + * fclose(f). Calling close(memfd) afterwards is undefined. + */ + ret = lseek(memfd, 0, SEEK_SET); + if (ret < 0) { + close(memfd); + WARN("%s - Failed to reset file descriptor offset", strerror(errno)); + return; + } + + f = fdopen(memfd, "r"); if (!f) { - SYSERROR("Failed to open \"/proc/self/mountinfo\" to mark all shared"); - ERROR("Continuing container startup..."); + WARN("Failed to open copy of \"/proc/self/mountinfo\" to mark " + "all shared. Continuing"); + close(memfd); return; } @@ -3210,10 +3260,13 @@ void remount_all_slave(void) if (ret < 0) { SYSERROR("Failed to make \"%s\" MS_SLAVE", target); ERROR("Continuing..."); + continue; } + TRACE("Remounted \"%s\" as MS_SLAVE", target); } fclose(f); free(line); + TRACE("Remounted all mount table entries as MS_SLAVE"); } static int lxc_execute_bind_init(struct lxc_handler *handler)