]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: move /dev setup to be file descriptor based
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 10 Aug 2020 09:01:42 +0000 (11:01 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 10 Aug 2020 09:01:42 +0000 (11:01 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h
src/lxc/file_utils.c
src/lxc/file_utils.h

index c6a240d6e3cd35b20f18463eea18cdba96330130..0a1bb6d75af96df0dc4170939424c685c122c349 100644 (file)
@@ -1610,15 +1610,15 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
        if (!wants_console(console))
                return 0;
 
-       ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
-       if (ret < 0 || (size_t)ret >= sizeof(path))
-               return -1;
-
        /*
         * When we are asked to setup a console we remove any previous
         * /dev/console bind-mounts.
         */
-       if (file_exists(path)) {
+       if (exists_file_at(rootfs->dev_mntpt_fd, "console")) {
+               ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
+               if (ret < 0 || (size_t)ret >= sizeof(path))
+                       return -1;
+
                ret = lxc_unstack_mountpoint(path, false);
                if (ret < 0)
                        return log_error_errno(-ret, errno, "Failed to unmount \"%s\"", path);
@@ -1630,7 +1630,7 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
         * For unprivileged containers autodev or automounts will already have
         * taken care of creating /dev/console.
         */
-       ret = mknod(path, S_IFREG | 0000, 0);
+       ret = mknodat(rootfs->dev_mntpt_fd, "console", S_IFREG | 0000, 0);
        if (ret < 0 && errno != EEXIST)
                return log_error_errno(-errno, errno, "Failed to create console");
 
@@ -1639,7 +1639,7 @@ static int lxc_setup_dev_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);
 
        if (pty_mnt_fd >= 0) {
-               ret = move_mount(pty_mnt_fd, "", -EBADF, path, MOVE_MOUNT_F_EMPTY_PATH);
+               ret = move_mount(pty_mnt_fd, "", rootfs->dev_mntpt_fd, "console", MOVE_MOUNT_F_EMPTY_PATH);
                if (!ret) {
                        DEBUG("Moved mount \"%s\" onto \"%s\"", console->name, path);
                        goto finish;
@@ -1651,9 +1651,18 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
                                               pty_mnt_fd, console->name, path);
        }
 
-       ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
-       if (ret < 0)
-               return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pty_mnt_fd, console->name, path);
+       ret = safe_mount_beneath_at(rootfs->dev_mntpt_fd, console->name, "console", NULL, MS_BIND, NULL);
+       if (ret < 0) {
+               if (errno == ENOSYS) {
+                       ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
+                       if (ret < 0 || (size_t)ret >= sizeof(path))
+                               return -1;
+
+                       ret = safe_mount(console->name, path, "none", MS_BIND, NULL, rootfs_path);
+                       if (ret < 0)
+                               return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pty_mnt_fd, console->name, path);
+               }
+       }
 
 finish:
        DEBUG("Mounted pty device %d(%s) onto \"%s\"", pty_mnt_fd, console->name, path);
@@ -2581,6 +2590,7 @@ struct lxc_conf *lxc_conf_init(void)
        }
        new->rootfs.managed = true;
        new->rootfs.mntpt_fd = -EBADF;
+       new->rootfs.dev_mntpt_fd = -EBADF;
        new->logfd = -1;
        lxc_list_init(&new->cgroup);
        lxc_list_init(&new->cgroup2);
@@ -3259,6 +3269,11 @@ int lxc_setup(struct lxc_handler *handler)
                        return log_error(-1, "Failed to mount \"/dev\"");
        }
 
+       lxc_conf->rootfs.dev_mntpt_fd = openat(lxc_conf->rootfs.mntpt_fd, "dev",
+                                               O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
+       if (lxc_conf->rootfs.dev_mntpt_fd < 0 && errno != ENOENT)
+               return log_error_errno(-errno, errno, "Failed to open \"/dev\"");
+
        /* Do automatic mounts (mainly /proc and /sys), but exclude those that
         * need to wait until other stuff has finished.
         */
@@ -3378,7 +3393,8 @@ int lxc_setup(struct lxc_handler *handler)
                return log_error(-1, "Failed to drop capabilities");
        }
 
-       close_prot_errno_disarm(lxc_conf->rootfs.mntpt_fd);
+       close_prot_errno_disarm(lxc_conf->rootfs.mntpt_fd)
+       close_prot_errno_disarm(lxc_conf->rootfs.dev_mntpt_fd)
        NOTICE("The container \"%s\" is set up", name);
 
        return 0;
@@ -3743,6 +3759,7 @@ void lxc_conf_free(struct lxc_conf *conf)
        free(conf->rootfs.path);
        free(conf->rootfs.data);
        close_prot_errno_disarm(conf->rootfs.mntpt_fd);
+       close_prot_errno_disarm(conf->rootfs.dev_mntpt_fd);
        free(conf->logfile);
        if (conf->logfd != -1)
                close(conf->logfd);
index bfdf3be314ae438b8531ed2d03f60b3aff7ce789..cd54b3fe0fd006ebb79f4dfadbf388a17d4c4018 100644 (file)
@@ -139,17 +139,19 @@ struct lxc_tty_info {
 
 /* Defines a structure to store the rootfs location, the
  * optionals pivot_root, rootfs mount paths
- * @path       : the rootfs source (directory or device)
- * @mount      : where it is mounted
- * @bev_type   : optional backing store type
- * @options    : mount options
- * @mountflags : the portion of @options that are flags
- * @data       : the portion of @options that are not flags
- * @managed    : whether it is managed by LXC
- * @mntpt_fd   : fd for @mount
+ * @path         : the rootfs source (directory or device)
+ * @mount        : where it is mounted
+ * @bev_type     : optional backing store type
+ * @options      : mount options
+ * @mountflags   : the portion of @options that are flags
+ * @data         : the portion of @options that are not flags
+ * @managed      : whether it is managed by LXC
+ * @mntpt_fd    : fd for @mount
+ * @dev_mntpt_fd : fd for /dev of the container
  */
 struct lxc_rootfs {
        int mntpt_fd;
+       int dev_mntpt_fd;
        char *path;
        char *mount;
        char *bdev_type;
index 46912642f71da0ccea82c3f6e8a63155011a2d4c..75bbc2eb25badd7e03c4ca9a94342751264e17ec 100644 (file)
@@ -551,3 +551,10 @@ bool exists_dir_at(int dir_fd, const char *path)
 
        return S_ISDIR(sb.st_mode);
 }
+
+bool exists_file_at(int dir_fd, const char *path)
+{
+       struct stat sb;
+
+       return fstatat(dir_fd, path, &sb, 0) == 0;
+}
index 48571185d28260d145bec9decc70bc109909a5ce..2455feb7fc54a0f5b44d8e89b279f4c9197687f4 100644 (file)
@@ -74,5 +74,6 @@ __hidden extern FILE *fdopen_cached(int fd, const char *mode, void **caller_free
 __hidden extern FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer);
 __hidden extern int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset);
 __hidden extern bool exists_dir_at(int dir_fd, const char *path);
+__hidden extern bool exists_file_at(int dir_fd, const char *path);
 
 #endif /* __LXC_FILE_UTILS_H */