]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: copy mountinfo for remount_all_slave() 2374/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 4 Jun 2018 10:49:05 +0000 (12:49 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 4 Jun 2018 11:15:16 +0000 (13:15 +0200)
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 <christian.brauner@ubuntu.com>
src/lxc/conf.c

index 05d58081e6d2ea03c4096f6fb4d058f5ea9acea1..48cd7f8b3ef3049e1839de88575f55a059a3d8c3 100644 (file)
@@ -43,6 +43,7 @@
 #include <sys/mount.h>
 #include <sys/param.h>
 #include <sys/prctl.h>
+#include <sys/sendfile.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
@@ -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)