]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: support console setup on containers without rootfs 3397/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 4 May 2020 11:26:43 +0000 (13:26 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 4 May 2020 11:26:43 +0000 (13:26 +0200)
This depends on the new mount api.

Closes #3164.
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
configure.ac
src/lxc/conf.c
src/lxc/macro.h
src/lxc/syscall_numbers.h
src/lxc/syscall_wrappers.h

index 6f1117c10d6aeb69032a37d9de507184e1388e03..d9365ac026944634181399aa2cb2ec9c53206fae 100644 (file)
@@ -622,7 +622,7 @@ AC_CHECK_HEADER([ifaddrs.h],
 AC_HEADER_MAJOR
 
 # Check for some syscalls functions
-AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create])
+AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree])
 
 # Check for strerror_r() support. Defines:
 # - HAVE_STRERROR_R if available
index 90d464f686f3b8646cab8717393c53340eb3f9f9..3753fd7a626b44398108c9983f47f0b80b3d5585 100644 (file)
@@ -1576,7 +1576,8 @@ static int setup_personality(int persona)
 }
 
 static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
-                                const struct lxc_terminal *console)
+                                const struct lxc_terminal *console,
+                                int pts_mnt_fd)
 {
        int ret;
        char path[PATH_MAX];
@@ -1589,7 +1590,8 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
        if (ret < 0 || (size_t)ret >= sizeof(path))
                return -1;
 
-       /* When we are asked to setup a console we remove any previous
+       /*
+        * When we are asked to setup a console we remove any previous
         * /dev/console bind-mounts.
         */
        if (file_exists(path)) {
@@ -1600,7 +1602,8 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
                        DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
        }
 
-       /* For unprivileged containers autodev or automounts will already have
+       /*
+        * For unprivileged containers autodev or automounts will already have
         * taken care of creating /dev/console.
         */
        ret = mknod(path, S_IFREG | 0000, 0);
@@ -1611,17 +1614,20 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
        if (ret < 0)
                return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name);
 
-       ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
+       if (pts_mnt_fd >= 0)
+               ret = move_mount(pts_mnt_fd, "", -EBADF, path, MOVE_MOUNT_F_EMPTY_PATH);
+       else
+               ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
        if (ret < 0)
-               return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, path);
+               return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pts_mnt_fd, console->name, path);
 
-       DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path);
+       DEBUG("Mounted pts device %d(%s) onto \"%s\"", pts_mnt_fd, console->name, path);
        return 0;
 }
 
 static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
                                    const struct lxc_terminal *console,
-                                   char *ttydir)
+                                   char *ttydir, int pts_mnt_fd)
 {
        int ret;
        char path[PATH_MAX], lxcpath[PATH_MAX];
@@ -1669,9 +1675,12 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
                return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name);
 
        /* bind mount console->name to '/dev/<ttydir>/console' */
-       ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path);
+       if (pts_mnt_fd >= 0)
+               ret = move_mount(pts_mnt_fd, "", -EBADF, path, MOVE_MOUNT_F_EMPTY_PATH);
+       else
+               ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path);
        if (ret < 0)
-               return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath);
+               return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pts_mnt_fd, console->name, lxcpath);
        DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
 
        /* bind mount '/dev/<ttydir>/console'  to '/dev/console'  */
@@ -1685,13 +1694,14 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
 }
 
 static int lxc_setup_console(const struct lxc_rootfs *rootfs,
-                            const struct lxc_terminal *console, char *ttydir)
+                            const struct lxc_terminal *console, char *ttydir,
+                            int pts_mnt_fd)
 {
 
        if (!ttydir)
-               return lxc_setup_dev_console(rootfs, console);
+               return lxc_setup_dev_console(rootfs, console, pts_mnt_fd);
 
-       return lxc_setup_ttydir_console(rootfs, console, ttydir);
+       return lxc_setup_ttydir_console(rootfs, console, ttydir, pts_mnt_fd);
 }
 
 static int parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size)
@@ -3267,6 +3277,7 @@ static int lxc_setup_boot_id(void)
 
 int lxc_setup(struct lxc_handler *handler)
 {
+       __do_close int pts_mnt_fd = -EBADF;
        int ret;
        const char *lxcpath = handler->lxcpath, *name = handler->name;
        struct lxc_conf *lxc_conf = handler->conf;
@@ -3305,6 +3316,12 @@ int lxc_setup(struct lxc_handler *handler)
                        return log_error(-1, "Failed to send network device names and ifindices to parent");
        }
 
+       pts_mnt_fd = open_tree(-EBADF, lxc_conf->console.name,
+                              OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_EMPTY_PATH);
+       if (pts_mnt_fd < 0)
+               SYSTRACE("Failed to create detached mount for container's console \"%s\"",
+                        lxc_conf->console.name);
+
        if (lxc_conf->autodev > 0) {
                ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath);
                if (ret < 0)
@@ -3377,8 +3394,12 @@ int lxc_setup(struct lxc_handler *handler)
        if (!verify_start_hooks(lxc_conf))
                return log_error(-1, "Failed to verify start hooks");
 
+       ret = lxc_create_tmp_proc_mount(lxc_conf);
+       if (ret < 0)
+               return log_error(-1, "Failed to \"/proc\" LSMs");
+
        ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
-                               lxc_conf->ttys.dir);
+                               lxc_conf->ttys.dir, pts_mnt_fd);
        if (ret < 0)
                return log_error(-1, "Failed to setup console");
 
@@ -3386,10 +3407,6 @@ int lxc_setup(struct lxc_handler *handler)
        if (ret < 0)
                return log_error(-1, "Failed to setup \"/dev\" symlinks");
 
-       ret = lxc_create_tmp_proc_mount(lxc_conf);
-       if (ret < 0)
-               return log_error(-1, "Failed to \"/proc\" LSMs");
-
        ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs);
        if (ret < 0)
                return log_error(-1, "Failed to pivot root into rootfs");
@@ -4476,8 +4493,8 @@ int userns_exec_mapped_root(const char *path, int path_fd,
        if (!gid_valid(container_host_gid))
                return log_error(-1, "No gid mapping for container root");
 
-       if (path) {
-               fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY);
+       if (path_fd < 0) {
+               fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_PATH);
                if (fd < 0)
                        return log_error_errno(-errno, errno, "Failed to open \"%s\"", path);
                target_fd = fd;
index 3df19d6d3aeab65c0e79bbba11899526d2a5c6a3..3a5bb0746422ca92c588722d3117574991ab71bd 100644 (file)
 #define CAP_SETGID 6
 #endif
 
+/* move_mount */
+#ifndef MOVE_MOUNT_F_EMPTY_PATH
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
+#endif
+
+/* open_tree */
+#ifndef OPEN_TREE_CLONE
+#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */
+#endif
+
+#ifndef OPEN_TREE_CLOEXEC
+#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */
+#endif
+
 /* prctl */
 #ifndef PR_CAPBSET_READ
 #define PR_CAPBSET_READ 23
index 94bac859a0d1339a88b77ce5b289c27f9ca456ad..e7a9dd9a4f4ed48f56e7d6da5d257373b041d67a 100644 (file)
        #endif
 #endif
 
+#ifndef __NR_move_mount
+       #if defined __alpha__
+               #define __NR_move_mount 539
+       #elif defined _MIPS_SIM
+               #if _MIPS_SIM == _MIPS_SIM_ABI32        /* o32 */
+                       #define __NR_move_mount 4429
+               #endif
+               #if _MIPS_SIM == _MIPS_SIM_NABI32       /* n32 */
+                       #define __NR_move_mount 6429
+               #endif
+               #if _MIPS_SIM == _MIPS_SIM_ABI64        /* n64 */
+                       #define __NR_move_mount 5429
+               #endif
+       #else
+               #define __NR_move_mount 429
+       #endif
+#endif
+
+#ifndef __NR_open_tree
+       #if defined __alpha__
+               #define __NR_open_tree 538
+       #elif defined _MIPS_SIM
+               #if _MIPS_SIM == _MIPS_SIM_ABI32        /* o32 */
+                       #define __NR_open_tree 4428
+               #endif
+               #if _MIPS_SIM == _MIPS_SIM_NABI32       /* n32 */
+                       #define __NR_open_tree 6428
+               #endif
+               #if _MIPS_SIM == _MIPS_SIM_ABI64        /* n64 */
+                       #define __NR_open_tree 5428
+               #endif
+       #else
+               #define __NR_open_tree 428
+       #endif
+#endif
+
 #endif /* __LXC_SYSCALL_NUMBERS_H */
index 1cef21585c70398bcae8ca6d9c109c4e0963d6ab..041daf3575979f44719dd016528fc68727cd77df 100644 (file)
@@ -137,4 +137,28 @@ static int faccessat(int __fd, const char *__file, int __type, int __flag)
 }
 #endif
 
+#ifndef HAVE_MOVE_MOUNT
+static inline int move_mount_lxc(int from_dfd, const char *from_pathname,
+                                int to_dfd, const char *to_pathname,
+                                unsigned int flags)
+{
+       return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd,
+                      to_pathname, flags);
+}
+#define move_mount move_mount_lxc
+#else
+extern int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
+                     const char *to_pathname, unsigned int flags);
+#endif
+
+#ifndef HAVE_OPEN_TREE
+static inline int open_tree_lxc(int dfd, const char *filename, unsigned int flags)
+{
+       return syscall(__NR_open_tree, dfd, filename, flags);
+}
+#define open_tree open_tree_lxc
+#else
+extern int open_tree(int dfd, const char *filename, unsigned int flags);
+#endif
+
 #endif /* __LXC_SYSCALL_WRAPPER_H */