From: Christian Brauner Date: Thu, 4 Feb 2021 10:22:26 +0000 (+0100) Subject: cgroups: fix cgroup mounting X-Git-Tag: lxc-5.0.0~301^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=315f8a4e427d41ab609023cf0986ef856c6f41a1;p=thirdparty%2Flxc.git cgroups: fix cgroup mounting Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 0276411ab..a14193bc9 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -45,6 +45,7 @@ #include "mainloop.h" #include "memory_utils.h" #include "storage/storage.h" +#include "syscall_wrappers.h" #include "utils.h" #ifndef HAVE_STRLCPY @@ -1805,11 +1806,12 @@ static inline int cg_mount_cgroup_full(int type, struct hierarchy *h, } __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, - struct lxc_handler *handler, - const char *root, int type) + struct lxc_conf *conf, int type) { __do_free char *cgroup_root = NULL; bool has_cgns = false, wants_force_mount = false; + struct lxc_rootfs *rootfs = &conf->rootfs; + const char *root = rootfs->path ? rootfs->mount : ""; int ret; if (!ops) @@ -1818,7 +1820,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, if (!ops->hierarchies) return true; - if (!handler || !handler->conf) + if (!conf) return ret_set_errno(false, EINVAL); if ((type & LXC_AUTO_CGROUP_MASK) == 0) @@ -1830,7 +1832,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, } if (!wants_force_mount) { - wants_force_mount = !lxc_wants_cap(CAP_SYS_ADMIN, handler->conf); + wants_force_mount = !lxc_wants_cap(CAP_SYS_ADMIN, conf); /* * Most recent distro versions currently have init system that @@ -1874,16 +1876,15 @@ __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 = safe_mount_beneath(root, NULL, - DEFAULT_CGROUP_MOUNTPOINT_RELATIVE, - "tmpfs", - MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, - "size=10240k,mode=755"); + ret = mount_at(rootfs->mntpt_fd, 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) { if (errno != ENOSYS) return log_error_errno(false, errno, "Failed to mount tmpfs on %s", - DEFAULT_CGROUP_MOUNTPOINT); + DEFAULT_CGROUP_MOUNTPOINT_RELATIVE); ret = safe_mount(NULL, cgroup_root, "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h index 82137564c..cfff2d755 100644 --- a/src/lxc/cgroups/cgroup.h +++ b/src/lxc/cgroups/cgroup.h @@ -172,8 +172,7 @@ struct cgroup_ops { bool (*chown)(struct cgroup_ops *ops, struct lxc_conf *conf); bool (*attach)(struct cgroup_ops *ops, const struct lxc_conf *conf, const char *name, const char *lxcpath, pid_t pid); - bool (*mount)(struct cgroup_ops *ops, struct lxc_handler *handler, - const char *root, int type); + bool (*mount)(struct cgroup_ops *ops, struct lxc_conf *conf, int type); bool (*devices_activate)(struct cgroup_ops *ops, struct lxc_handler *handler); bool (*monitor_delegate_controllers)(struct cgroup_ops *ops); diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 893485de2..97556ee98 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -734,10 +734,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha if (flags & LXC_AUTO_CGROUP_FORCE) cg_flags |= LXC_AUTO_CGROUP_FORCE; - if (!handler->cgroup_ops->mount(handler->cgroup_ops, - handler, - rootfs->path ? rootfs->mount : "", - cg_flags)) + if (!handler->cgroup_ops->mount(handler->cgroup_ops, conf, cg_flags)) return log_error_errno(-1, errno, "Failed to mount \"/sys/fs/cgroup\""); } diff --git a/src/lxc/utils.c b/src/lxc/utils.c index e94765086..0938ffee1 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1208,6 +1208,58 @@ 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(dst_under_dfd)) + return log_error_errno(-EINVAL, EINVAL, "No target 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; + } + + 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); + + ret = snprintf(dst_buf, sizeof(dst_buf), "/proc/self/fd/%d", target_fd); + 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 open_devnull(void) { int fd = open("/dev/null", O_RDWR); diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 790ea4ad0..dc22394fc 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -243,5 +243,9 @@ __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); #endif /* __LXC_UTILS_H */