From de7f9f3303a5ed1100e6e0683a4a9fa4eb8330cc Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 11 Feb 2021 14:51:46 +0100 Subject: [PATCH] tree-wide: rework mount api support checks Signed-off-by: Christian Brauner --- src/lxc/cgroups/cgfsng.c | 4 ++-- src/lxc/conf.c | 14 +++++------ src/lxc/mount_utils.c | 50 ++++++++++++++++++++++++++++++++++++++++ src/lxc/mount_utils.h | 24 ++----------------- 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 44b9d7c00..aff6bc852 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1800,7 +1800,7 @@ static int __cg_mount_direct(int type, struct hierarchy *h, fstype = "cgroup"; } - if (new_mount_api()) { + if (can_use_mount_api()) { fd_fs = fs_prepare(fstype, -EBADF, "", 0, 0); if (fd_fs < 0) return log_error_errno(-errno, errno, "Failed to prepare filesystem context for %s", fstype); @@ -1946,7 +1946,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, * relying on RESOLVE_BENEATH so we need to skip the leading "/" in the * DEFAULT_CGROUP_MOUNTPOINT define. */ - if (new_mount_api()) { + if (can_use_mount_api()) { fd_fs = fs_prepare("tmpfs", -EBADF, "", 0, 0); if (fd_fs < 0) return log_error_errno(-errno, errno, "Failed to create new filesystem context for tmpfs"); diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 4cf91a7ee..5a69d3d98 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -844,7 +844,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) "Failed to unlink %d(%s)", rootfs->dfd_dev, tty_name); - if (new_mount_api()) { + if (can_use_mount_api()) { ret = fd_bind_mount(tty->pty, "", PROTECT_OPATH_FILE, PROTECT_LOOKUP_BENEATH_XDEV, @@ -881,7 +881,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) "Failed to create tty mount target %d(%s)", rootfs->dfd_dev, rootfs->buf); - if (new_mount_api()) { + if (can_use_mount_api()) { ret = fd_bind_mount(tty->pty, "", PROTECT_OPATH_FILE, PROTECT_LOOKUP_BENEATH_XDEV, @@ -1074,7 +1074,7 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, goto reset_umask; } - if (new_mount_api()) { + if (can_use_mount_api()) { fd_fs = fs_prepare("tmpfs", -EBADF, "", 0, 0); if (fd_fs < 0) return log_error_errno(-errno, errno, "Failed to prepare filesystem context for tmpfs"); @@ -1216,7 +1216,7 @@ static int lxc_fill_autodev(struct lxc_rootfs *rootfs) if (ret < 0) return ret_errno(EIO); - if (new_mount_api()) { + if (can_use_mount_api()) { ret = fd_bind_mount(rootfs->dfd_host, rootfs->buf, PROTECT_OPATH_FILE, PROTECT_LOOKUP_BENEATH_XDEV, @@ -1716,7 +1716,7 @@ static int lxc_setup_dev_console(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); - if (new_mount_api()) { + if (can_use_mount_api()) { ret = lxc_bind_mount_console(console, rootfs->dfd_dev, "console"); } else { ret = strnprintf(rootfs->buf, sizeof(rootfs->buf), "%s/dev/console", rootfs_path); @@ -1779,7 +1779,7 @@ static int lxc_setup_ttydir_console(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//console' */ - if (new_mount_api()) { + if (can_use_mount_api()) { ret = strnprintf(rootfs->buf, sizeof(rootfs->buf), "%s/console", ttydir); if (ret < 0) return ret; @@ -1793,7 +1793,7 @@ static int lxc_setup_ttydir_console(struct lxc_rootfs *rootfs, DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); /* bind mount '/dev//console' to '/dev/console' */ - if (new_mount_api()) { + if (can_use_mount_api()) { ret = fd_bind_mount(rootfs->dfd_dev, rootfs->buf, PROTECT_OPATH_FILE, PROTECT_LOOKUP_BENEATH_XDEV, rootfs->dfd_dev, "console", diff --git a/src/lxc/mount_utils.c b/src/lxc/mount_utils.c index 5132ea226..c0d5a4535 100644 --- a/src/lxc/mount_utils.c +++ b/src/lxc/mount_utils.c @@ -438,3 +438,53 @@ unsigned long add_required_remount_flags(const char *s, const char *d, return flags; #endif } + +bool can_use_mount_api(void) +{ + static int supported = -1; + + if (supported == -1) { + __do_close int fd = -EBADF; + + fd = openat2(-EBADF, "", NULL, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + fd = fsmount(-EBADF, 0, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + fd = fsconfig(-EBADF, -EINVAL, NULL, NULL, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + fd = fsopen(NULL, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + fd = move_mount(-EBADF, NULL, -EBADF, NULL, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + fd = open_tree(-EBADF, NULL, 0); + if (fd > 0 || errno == ENOSYS) { + supported = 0; + return false; + } + + supported = 1; + TRACE("Kernel supports mount api"); + } + + return supported == 1; +} diff --git a/src/lxc/mount_utils.h b/src/lxc/mount_utils.h index 9e28eccf4..d38581d9b 100644 --- a/src/lxc/mount_utils.h +++ b/src/lxc/mount_utils.h @@ -185,28 +185,6 @@ __hidden extern int fd_bind_mount(int dfd_from, const char *path_from, __u64 o_flags_to, __u64 resolve_flags_to, unsigned int attr_flags, bool recursive); -/* - * We use openat2() as indicator whether or not the new mount api is supported. - * First, because openat2() has been introduced after all syscalls from the new - * mount api we currently use and second because our hardened mount logic - * relies on openat2() to safely resolve paths. - */ -static inline bool new_mount_api(void) -{ - __do_close int fd = -EBADF; - static int supported = -1; - - if (supported == -1) { - fd = openat2(-EBADF, "", NULL, 0); - if (fd < 0 && errno != ENOSYS) - supported = 1; - else - supported = 0; - } - - return supported == 1; -} - __hidden extern int calc_remount_flags_new(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, @@ -223,4 +201,6 @@ __hidden extern unsigned long add_required_remount_flags(const char *s, const char *d, unsigned long flags); +__hidden extern bool can_use_mount_api(void); + #endif /* __LXC_MOUNT_UTILS_H */ -- 2.47.2