Unverified Commit 338c2abe by Stéphane Graber Committed by GitHub

Merge pull request #3659 from brauner/2021-02-05/fixes

mount: extend support for the new mount api
parents b5daeddc 635e7bac
......@@ -356,6 +356,7 @@ lxc_attach_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -413,6 +414,7 @@ lxc_autostart_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -469,6 +471,7 @@ lxc_cgroup_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -525,6 +528,7 @@ lxc_config_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -581,6 +585,7 @@ lxc_console_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -637,6 +642,7 @@ lxc_destroy_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -693,6 +699,7 @@ lxc_device_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -749,6 +756,7 @@ lxc_execute_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -805,6 +813,7 @@ lxc_freeze_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -861,6 +870,7 @@ lxc_info_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -918,6 +928,7 @@ lxc_monitor_SOURCES += af_unix.c af_unix.h \
macro.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -975,6 +986,7 @@ lxc_ls_SOURCES += af_unix.c af_unix.h \
mainloop.c mainloop.h \
memory_utils.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1031,6 +1043,7 @@ lxc_copy_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1087,6 +1100,7 @@ lxc_start_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1143,6 +1157,7 @@ lxc_stop_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1199,6 +1214,7 @@ lxc_top_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1255,6 +1271,7 @@ lxc_unfreeze_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1311,6 +1328,7 @@ lxc_unshare_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1369,6 +1387,7 @@ lxc_wait_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1425,6 +1444,7 @@ lxc_create_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1481,6 +1501,7 @@ lxc_snapshot_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1537,6 +1558,7 @@ lxc_checkpoint_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1608,6 +1630,7 @@ lxc_monitord_SOURCES += af_unix.c af_unix.h \
lxclock.c lxclock.h \
mainloop.c mainloop.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1665,6 +1688,7 @@ lxc_user_nic_SOURCES += af_unix.c af_unix.h \
mainloop.c mainloop.h \
memory_utils.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......@@ -1725,6 +1749,7 @@ lxc_usernsexec_SOURCES += af_unix.c af_unix.h \
mainloop.c mainloop.h \
memory_utils.h \
monitor.c monitor.h \
mount_utils.c mount_utils.h \
namespace.c namespace.h \
network.c network.h \
nl.c nl.h \
......
......@@ -44,6 +44,7 @@
#include "macro.h"
#include "mainloop.h"
#include "memory_utils.h"
#include "mount_utils.h"
#include "storage/storage.h"
#include "syscall_wrappers.h"
#include "utils.h"
......@@ -1762,42 +1763,65 @@ static int __cg_mount_direct(int type, struct hierarchy *h,
struct lxc_rootfs *rootfs,
int dfd_mnt_cgroupfs, const char *hierarchy_mnt)
{
__do_free char *controllers = NULL;
unsigned long flags = 0;
__do_close int fd_fs = -EBADF;
unsigned int flags = 0;
char *fstype;
int ret;
if (dfd_mnt_cgroupfs < 0)
return ret_errno(EINVAL);
flags |= MS_NOSUID;
flags |= MS_NOEXEC;
flags |= MS_NODEV;
flags |= MS_RELATIME;
flags |= MOUNT_ATTR_NOSUID;
flags |= MOUNT_ATTR_NOEXEC;
flags |= MOUNT_ATTR_NODEV;
flags |= MOUNT_ATTR_RELATIME;
if (type == LXC_AUTO_CGROUP_RO || type == LXC_AUTO_CGROUP_FULL_RO)
flags |= MS_RDONLY;
flags |= MOUNT_ATTR_RDONLY;
if (is_unified_hierarchy(h)) {
fstype = "cgroup2";
} else {
fstype = "cgroup";
controllers = lxc_string_join(",", (const char **)h->controllers, false);
if (!controllers)
return ret_errno(ENOMEM);
}
ret = mount_at(dfd_mnt_cgroupfs, NULL, hierarchy_mnt,
PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH, fstype,
flags, controllers);
if (ret < 0 && errno == ENOSYS) {
__do_free char *target = NULL;
if (new_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);
if (!is_unified_hierarchy(h)) {
for (const char **it = (const char **)h->controllers; it && *it; it++) {
if (strncmp(*it, "name=", STRLITERALLEN("name=")) == 0)
ret = fs_set_property(fd_fs, "name", *it + STRLITERALLEN("name="));
else
ret = fs_set_property(fd_fs, *it, "");
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to add %s controller to cgroup filesystem context %d(dev)", *it, fd_fs);
}
}
ret = fs_attach(fd_fs, dfd_mnt_cgroupfs, hierarchy_mnt,
PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH,
flags);
} else {
__do_free char *controllers = NULL, *target = NULL;
unsigned int old_flags = 0;
const char *rootfs_mnt;
if (!is_unified_hierarchy(h)) {
controllers = lxc_string_join(",", (const char **)h->controllers, false);
if (!controllers)
return ret_errno(ENOMEM);
}
rootfs_mnt = get_rootfs_mnt(rootfs);
ret = mnt_attributes_old(flags, &old_flags);
if (ret)
return log_error_errno(-EINVAL, EINVAL, "Unsupported mount properties specified");
target = must_make_path(rootfs_mnt, DEFAULT_CGROUP_MOUNTPOINT, hierarchy_mnt, NULL);
ret = safe_mount(NULL, target, fstype, flags, controllers, rootfs_mnt);
ret = safe_mount(NULL, target, fstype, old_flags, controllers, rootfs_mnt);
}
if (ret < 0)
return log_error_errno(ret, errno, "Failed to mount %s filesystem onto %d(%s)",
......@@ -1830,7 +1854,7 @@ static inline int cg_mount_cgroup_full(int type, struct hierarchy *h,
__cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops,
struct lxc_conf *conf, int type)
{
__do_close int dfd_mnt_cgroupfs = -EBADF;
__do_close int dfd_mnt_cgroupfs = -EBADF, fd_fs = -EBADF;
__do_free char *cgroup_root = NULL;
bool has_cgns = false, wants_force_mount = false;
struct lxc_rootfs *rootfs = &conf->rootfs;
......@@ -1907,13 +1931,25 @@ __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.
*/
ret = mount_at(rootfs->dfd_mnt, NULL, DEFAULT_CGROUP_MOUNTPOINT_RELATIVE,
PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH_XDEV,
"tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME,
"size=10240k,mode=755");
if (ret < 0 && errno == ENOSYS) {
cgroup_root = must_make_path(rootfs_mnt, DEFAULT_CGROUP_MOUNTPOINT, NULL);
if (new_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");
ret = fs_set_property(fd_fs, "mode", "0755");
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to mount tmpfs onto %d(dev)", fd_fs);
ret = fs_set_property(fd_fs, "size", "10240k");
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to mount tmpfs onto %d(dev)", fd_fs);
ret = fs_attach(fd_fs, rootfs->dfd_mnt, DEFAULT_CGROUP_MOUNTPOINT_RELATIVE,
PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH_XDEV,
MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV |
MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RELATIME);
} else {
cgroup_root = must_make_path(rootfs_mnt, DEFAULT_CGROUP_MOUNTPOINT, NULL);
ret = safe_mount(NULL, cgroup_root, "tmpfs",
MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME,
"size=10240k,mode=755", rootfs_mnt);
......
......@@ -1060,16 +1060,15 @@ on_error:
static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
int autodevtmpfssize, const char *lxcpath)
{
__do_close int fd_fs = -EBADF;
const char *path = rootfs->path ? rootfs->mount : NULL;
size_t tmpfs_size = (autodevtmpfssize != 0) ? autodevtmpfssize : 500000;
int ret;
mode_t cur_mask;
char mount_options[128];
INFO("Preparing \"/dev\"");
sprintf(mount_options, "size=%d,mode=755", (autodevtmpfssize != 0) ? autodevtmpfssize : 500000);
DEBUG("Using mount options: %s", mount_options);
cur_mask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
ret = mkdirat(rootfs->dfd_mnt, "dev" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret < 0 && errno != EEXIST) {
......@@ -1078,14 +1077,27 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
goto reset_umask;
}
ret = safe_mount_beneath_at(rootfs->dfd_mnt, "none", "dev", "tmpfs", 0, mount_options);
if (ret < 0) {
if (new_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");
sprintf(mount_options, "%zu", tmpfs_size);
ret = fs_set_property(fd_fs, "mode", "0755");
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to mount tmpfs onto %d(dev)", fd_fs);
ret = fs_set_property(fd_fs, "size", mount_options);
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to mount tmpfs onto %d(dev)", fd_fs);
ret = fs_attach(fd_fs, rootfs->dfd_mnt, "dev", PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH, 0);
} else {
__do_free char *fallback_path = NULL;
if (errno != ENOSYS) {
SYSERROR("Failed to mount tmpfs on \"%s\"", path);
goto reset_umask;
}
sprintf(mount_options, "size=%zu,mode=755", tmpfs_size);
DEBUG("Using mount options: %s", mount_options);
if (path) {
fallback_path = must_make_path(path, "/dev", NULL);
......@@ -1093,19 +1105,19 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
} else {
ret = safe_mount("none", "dev", "tmpfs", 0, mount_options, NULL);
}
if (ret < 0) {
SYSERROR("Failed to mount tmpfs on \"%s\"", path);
goto reset_umask;
}
}
TRACE("Mounted tmpfs on \"%s\"", path);
if (ret < 0) {
SYSERROR("Failed to mount tmpfs on \"%s\"", path);
goto reset_umask;
}
/* If we are running on a devtmpfs mapping, dev/pts may already exist.
* If not, then create it and exit if that fails...
*/
ret = mkdirat(rootfs->dfd_mnt, "dev/pts", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create directory \"%s\"", path);
SYSERROR("Failed to create directory \"dev/pts\"");
ret = -errno;
goto reset_umask;
}
......@@ -1208,26 +1220,16 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
if (ret < 0 || (size_t)ret >= sizeof(device_path))
return ret_errno(EIO);
ret = mount_from_at(rootfs->dfd_host, device_path,
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH_XDEV,
rootfs->dfd_dev, device->name,
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH,
NULL /* fstype */,
MS_BIND /* mount flags */,
NULL);
if (ret < 0) {
if (new_mount_api()) {
ret = fd_bind_mount(rootfs->dfd_host, device_path,
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH_XDEV,
rootfs->dfd_dev, device->name,
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH, 0, false);
} else {
char path[PATH_MAX];
if (errno != ENOSYS)
return log_error_errno(-errno, errno,
"Failed to mount %d(%s) to %d(%s)",
rootfs->dfd_host,
device_path,
rootfs->dfd_dev,
device->name);
ret = snprintf(device_path, sizeof(device_path), "/dev/%s", device->name);
if (ret < 0 || (size_t)ret >= sizeof(device_path))
return ret_errno(EIO);
......
......@@ -4,6 +4,7 @@
#define _GNU_SOURCE 1
#endif
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
......@@ -138,3 +139,172 @@ int mount_filesystem(const char *fs_name, const char *path, unsigned int attr_fl
mnt_attributes_old(attr_flags, &old_flags);
return mount("none", path, fs_name, old_flags, NULL);
}
static int __fs_prepare(const char *fs_name, int fd_from)
{
__do_close int fd_fs = -EBADF;
char source[LXC_PROC_PID_FD_LEN];
int ret;
/* This helper is only concerned with filesystems. */
if (is_empty_string(fs_name))
return ret_errno(EINVAL);
/*
* So here is where I'm a bit disappointed. The new mount api doesn't
* let you specify the block device source through an fd. You need to
* pass a path which is obviously crap and runs afoul of the mission to
* only use fds for mount.
*/
if (fd_from >= 0) {
ret = snprintf(source, sizeof(source), "/proc/self/fd/%d", fd_from);
if (ret < 0 || ret >= sizeof(source))
return log_error_errno(-EIO, EIO, "Failed to create /proc/self/fd/%d", fd_from);
}
fd_fs = fsopen(fs_name, FSOPEN_CLOEXEC);
if (fd_fs < 0)
return log_error_errno(-errno, errno, "Failed to create new open new %s filesystem context", fs_name);
if (fd_from >= 0) {
ret = fsconfig(fd_fs, FSCONFIG_SET_STRING, "source", source, 0);
if (ret)
return log_error_errno(-errno, errno, "Failed to set %s filesystem source to %s", fs_name, source);
TRACE("Set %s filesystem source property to %s", fs_name, source);
}
TRACE("Finished initializing new %s filesystem context %d", fs_name, fd_fs);
return move_fd(fd_fs);
}
int fs_prepare(const char *fs_name,
int dfd_from, const char *path_from,
__u64 o_flags_from, __u64 resolve_flags_from)
{
__do_close int __fd_from = -EBADF;
int fd_from;
if (!is_empty_string(path_from)) {
struct lxc_open_how how = {
.flags = o_flags_from,
.resolve = resolve_flags_from,
};
__fd_from = openat2(dfd_from, path_from, &how, sizeof(how));
if (__fd_from < 0)
return -errno;
fd_from = __fd_from;
} else {
fd_from = dfd_from;
}
return __fs_prepare(fs_name, fd_from);
}
int fs_set_property(int fd_fs, const char *key, const char *val)
{
int ret;
ret = fsconfig(fd_fs, FSCONFIG_SET_STRING, key, val, 0);
if (ret < 0)
return log_error_errno(-errno, errno,
"Failed to set \"%s\" to \"%s\" on filesystem context %d",
key, val, fd_fs);
TRACE("Set \"%s\" to \"%s\" on filesystem context %d", key, val, fd_fs);
return 0;
}
int fs_attach(int fd_fs,
int dfd_to, const char *path_to,
__u64 o_flags_to, __u64 resolve_flags_to,
unsigned int attr_flags)
{
__do_close int __fd_to = -EBADF, fd_fsmnt = -EBADF;
int fd_to, ret;
if (!is_empty_string(path_to)) {
struct lxc_open_how how = {
.flags = o_flags_to,
.resolve = resolve_flags_to,
};
__fd_to = openat2(dfd_to, path_to, &how, sizeof(how));
if (__fd_to < 0)
return -errno;
fd_to = __fd_to;
} else {
fd_to = dfd_to;
}
ret = fsconfig(fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
if (ret < 0)
return log_error_errno(-errno, errno, "Failed to finalize filesystem context %d", fd_fs);
fd_fsmnt = fsmount(fd_fs, FSMOUNT_CLOEXEC, attr_flags);
if (fd_fsmnt < 0)
return log_error_errno(-errno, errno,
"Failed to create new mount for filesystem context %d", fd_fs);
ret = move_mount(fd_fsmnt, "", fd_to, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH);
if (ret)
return log_error_errno(-errno, errno, "Failed to mount %d onto %d", fd_fsmnt, fd_to);
TRACE("Mounted %d onto %d", fd_fsmnt, fd_to);
return 0;
}
int fd_bind_mount(int dfd_from, const char *path_from,
__u64 o_flags_from, __u64 resolve_flags_from,
int dfd_to, const char *path_to,
__u64 o_flags_to, __u64 resolve_flags_to,
unsigned int attr_flags, bool recursive)
{
__do_close int __fd_from = -EBADF, __fd_to = -EBADF;
__do_close int fd_tree_from = -EBADF;
unsigned int open_tree_flags = AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLONE;
int fd_from, fd_to, ret;
if (!is_empty_string(path_from)) {
struct lxc_open_how how = {
.flags = o_flags_from,
.resolve = resolve_flags_from,
};
__fd_from = openat2(dfd_from, path_from, &how, sizeof(how));
if (__fd_from < 0)
return -errno;
fd_from = __fd_from;
} else {
fd_from = dfd_from;
}
if (recursive)
open_tree_flags |= AT_RECURSIVE;
fd_tree_from = open_tree(fd_from, "", open_tree_flags);
if (fd_tree_from < 0)
return log_error_errno(-errno, errno, "Failed to create detached mount");
if (!is_empty_string(path_to)) {
struct lxc_open_how how = {
.flags = o_flags_to,
.resolve = resolve_flags_to,
};
__fd_to = openat2(dfd_to, path_to, &how, sizeof(how));
if (__fd_to < 0)
return -errno;
fd_to = __fd_to;
} else {
fd_to = dfd_to;
}
ret = move_mount(fd_tree_from, "", fd_to, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH);
if (ret)
return log_error_errno(-errno, errno, "Failed to attach detached mount %d to filesystem at %d", fd_tree_from, fd_to);
TRACE("Attach detached mount %d to filesystem at %d", fd_tree_from, fd_to);
return 0;
}
......@@ -3,13 +3,21 @@
#ifndef __LXC_MOUNT_UTILS_H
#define __LXC_MOUNT_UTILS_H
#include <linux/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
#include "compiler.h"
#include "memory_utils.h"
#include "syscall_wrappers.h"
/* open_tree() flags */
#ifndef AT_RECURSIVE
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
#endif
#ifndef OPEN_TREE_CLONE
#define OPEN_TREE_CLONE 1
#endif
......@@ -150,4 +158,55 @@ __hidden extern int mnt_attributes_old(unsigned int new_flags, unsigned int *old
__hidden extern int mount_filesystem(const char *fs_name, const char *path, unsigned int attr_flags);
__hidden extern int fs_prepare(const char *fs_name, int dfd_from,
const char *path_from, __u64 o_flags_from,
__u64 resolve_flags_from);
__hidden extern int fs_set_property(int fd_fs, const char *key, const char *val);
__hidden extern int fs_attach(int fd_fs, int dfd_to, const char *path_to,
__u64 o_flags_to, __u64 resolve_flags_to,
unsigned int attr_flags);
static inline int fs_mount(const char *fs_name, int dfd_from,
const char *path_from, __u64 o_flags_from,
__u64 resolve_flags_from, int dfd_to,
const char *path_to, __u64 o_flags_to,
__u64 resolve_flags_to,
unsigned int attr_flags)
{
__do_close int fd_fs = -EBADF;
fd_fs = fs_prepare(fs_name, dfd_from, path_from, o_flags_from, resolve_flags_from);
if (fd_fs < 0)
return -errno;
return fs_attach(fd_fs, dfd_to, path_to, o_flags_to, resolve_flags_to, attr_flags);
}
__hidden extern int fd_bind_mount(int dfd_from, const char *path_from,
__u64 o_flags_from, __u64 resolve_flags_from,
int dfd_to, const char *path_to,
__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;
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;
}
#endif /* __LXC_MOUNT_UTILS_H */
......@@ -1208,110 +1208,6 @@ int safe_mount(const char *src, const char *dest, const char *fstype,
return 0;
}
int mount_at(int dfd,
const char *src_under_dfd,
const char *dst_under_dfd,
__u64 o_flags,
__u64 resolve_flags,
const char *fstype,
unsigned int mnt_flags,
const void *data)
{
__do_close int source_fd = -EBADF, target_fd = -EBADF;
struct lxc_open_how how = {
.flags = o_flags,
.resolve = resolve_flags,
};
int ret;
char src_buf[LXC_PROC_PID_FD_LEN], dst_buf[LXC_PROC_PID_FD_LEN];
if (dfd < 0)
return ret_errno(EINVAL);
if (!is_empty_string(src_buf) && *src_buf == '/')
return log_error_errno(-EINVAL, EINVAL, "Absolute path specified");
if (!is_empty_string(src_under_dfd)) {
source_fd = openat2(dfd, src_under_dfd, &how, sizeof(how));
if (source_fd < 0)
return -errno;
ret = snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", source_fd);
if (ret < 0 || ret >= sizeof(src_buf))
return -EIO;
}
if (!is_empty_string(dst_under_dfd)) {
target_fd = openat2(dfd, dst_under_dfd, &how, sizeof(how));
if (target_fd < 0)
return log_error_errno(-errno, errno, "Failed to open %d(%s)", dfd, dst_under_dfd);
TRACE("Mounting %d(%s) through /proc/self/fd/%d", target_fd, dst_under_dfd, target_fd);
ret = snprintf(dst_buf, sizeof(dst_buf), "/proc/self/fd/%d", target_fd);
} else {
TRACE("Mounting %d through /proc/self/fd/%d", dfd, dfd);
ret = snprintf(dst_buf, sizeof(dst_buf), "/proc/self/fd/%d", dfd);
}
if (ret < 0 || ret >= sizeof(dst_buf))
return -EIO;
if (!is_empty_string(src_buf))
ret = mount(src_buf, dst_buf, fstype, mnt_flags, data);
else
ret = mount(NULL, dst_buf, fstype, mnt_flags, data);
return ret;
}
int mount_from_at(int dfd_from, const char *path_from,
__u64 o_flags_from,
__u64 resolve_flags_from,
int dfd_to, const char *path_to,
__u64 o_flags_to,
__u64 resolve_flags_to,
const char *fstype, unsigned int mnt_flags, const void *data)
{
__do_close int fd_from = -EBADF, fd_to = -EBADF;
struct lxc_open_how how = {};
int ret;
char src_buf[LXC_PROC_PID_FD_LEN], dst_buf[LXC_PROC_PID_FD_LEN];
if (is_empty_string(path_from)) {
ret = snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", dfd_from);
} else {
how.flags = o_flags_from;
how.resolve = resolve_flags_from;
fd_from = openat2(dfd_from, path_from, &how, sizeof(how));
if (fd_from < 0)
return -errno;
ret = snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", fd_from);
}
if (ret < 0 || ret >= sizeof(src_buf))
return -EIO;
if (is_empty_string(path_to)) {
ret = snprintf(dst_buf, sizeof(dst_buf), "/proc/self/fd/%d", dfd_to);
} else {
how.flags = o_flags_to;
how.resolve = resolve_flags_to;
fd_to = openat2(dfd_to, path_to, &how, sizeof(how));
if (fd_to < 0)
return -errno;
ret = snprintf(dst_buf, sizeof(dst_buf), "/proc/self/fd/%d", fd_to);
}
if (ret < 0 || ret >= sizeof(src_buf))
return -EIO;
if (is_empty_string(src_buf))
ret = mount(NULL, dst_buf, fstype, mnt_flags, data);
else
ret = mount(src_buf, dst_buf, fstype, mnt_flags, data);
return ret;
}
int open_devnull(void)
{
int fd = open("/dev/null", O_RDWR);
......
......@@ -244,15 +244,5 @@ __hidden extern int safe_mount_beneath(const char *beneath, const char *src, con
const char *fstype, unsigned int flags, const void *data);
__hidden extern int safe_mount_beneath_at(int beneat_fd, const char *src, const char *dst,
const char *fstype, unsigned int flags, const void *data);
__hidden extern int mount_at(int dfd, const char *src_under_dfd,
const char *dst_under_dfd, __u64 o_flags,
__u64 resolve_flags, const char *fstype,
unsigned int mnt_flags, const void *data);
__hidden extern int mount_from_at(int dfd_from, const char *path_from,
__u64 o_flags_from, __u64 resolve_flags_from,
int dfd_to, const char *path_to,
__u64 o_flags_to, __u64 resolve_flags_to,
const char *fstype, unsigned int mnt_flags,
const void *data);
#endif /* __LXC_UTILS_H */
......@@ -39,6 +39,7 @@ lxc_test_api_reboot_SOURCES = api_reboot.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -88,6 +89,7 @@ lxc_test_apparmor_SOURCES = aa.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -137,6 +139,7 @@ lxc_test_attach_SOURCES = attach.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -187,6 +190,7 @@ lxc_test_cgpath_SOURCES = cgpath.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -239,6 +243,7 @@ lxc_test_config_jump_table_SOURCES = config_jump_table.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -295,6 +300,7 @@ lxc_test_device_add_remove_SOURCES = device_add_remove.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -344,6 +350,7 @@ lxc_test_get_item_SOURCES = get_item.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -393,6 +400,7 @@ lxc_test_locktests_SOURCES = locktests.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -445,6 +453,7 @@ lxc_test_mount_injection_SOURCES = mount_injection.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -495,6 +504,7 @@ lxc_test_parse_config_file_SOURCES = parse_config_file.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -545,6 +555,7 @@ lxc_test_raw_clone_SOURCES = lxc_raw_clone.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......@@ -609,6 +620,7 @@ lxc_test_utils_SOURCES = lxc-test-utils.c \
../lxc/lxclock.c ../lxc/lxclock.h \
../lxc/mainloop.c ../lxc/mainloop.h \
../lxc/monitor.c ../lxc/monitor.h \
../lxc/mount_utils.c ../lxc/mount_utils.h \
../lxc/namespace.c ../lxc/namespace.h \
../lxc/network.c ../lxc/network.h \
../lxc/nl.c ../lxc/nl.h \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment