Skip to content

Commit

Permalink
tree-wide: rework mount api support checks
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Feb 26, 2021
1 parent c0886b8 commit aeb0b9b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 31 deletions.
4 changes: 2 additions & 2 deletions src/lxc/cgroups/cgfsng.c
Expand Up @@ -1799,7 +1799,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);
Expand Down Expand Up @@ -1945,7 +1945,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");
Expand Down
14 changes: 7 additions & 7 deletions src/lxc/conf.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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/<ttydir>/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;
Expand All @@ -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/<ttydir>/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",
Expand Down
50 changes: 50 additions & 0 deletions src/lxc/mount_utils.c
Expand Up @@ -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;
}
24 changes: 2 additions & 22 deletions src/lxc/mount_utils.h
Expand Up @@ -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,
Expand All @@ -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 */

0 comments on commit aeb0b9b

Please sign in to comment.