From: Christian Brauner Date: Mon, 10 Aug 2020 09:01:42 +0000 (+0200) Subject: conf: move /dev setup to be file descriptor based X-Git-Tag: lxc-5.0.0~369^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=953db219dab62555dd9e515561a918db8f47ee4a;p=thirdparty%2Flxc.git conf: move /dev setup to be file descriptor based Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index c6a240d6e..0a1bb6d75 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index bfdf3be31..cd54b3fe0 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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; diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c index 46912642f..75bbc2eb2 100644 --- a/src/lxc/file_utils.c +++ b/src/lxc/file_utils.c @@ -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; +} diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h index 48571185d..2455feb7f 100644 --- a/src/lxc/file_utils.h +++ b/src/lxc/file_utils.h @@ -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 */