]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgroups: fix cgroup mounting
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 4 Feb 2021 10:22:26 +0000 (11:22 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 4 Feb 2021 14:59:50 +0000 (15:59 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/cgroups/cgroup.h
src/lxc/conf.c
src/lxc/utils.c
src/lxc/utils.h

index 0276411ab94c2d1527f8e8b0ef05d9e960960424..a14193bc9f67ab7a8341d7d05ceaa9a5523fd36f 100644 (file)
@@ -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,
index 82137564c0ff8ac07a68b929962c1492c2145724..cfff2d7550e4204b071219f8e7d11a26ffd3cd67 100644 (file)
@@ -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);
index 893485de2ab0705c49da29339b13f683c1f393fe..97556ee983b0b02423dc3e4f0fd72389f148d531 100644 (file)
@@ -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\"");
        }
 
index e947650860f33ad2bfa81feb6688dcc999753702..0938ffee160acea8ae77b6b8839583aa175ec472 100644 (file)
@@ -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);
index 790ea4ad0427e6321804d974eb3062647460b840..dc22394fc09e377385ee29461c06bed1992de89e 100644 (file)
@@ -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 */