#include "mainloop.h"
#include "memory_utils.h"
#include "storage/storage.h"
+#include "syscall_wrappers.h"
#include "utils.h"
#ifndef HAVE_STRLCPY
}
__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)
if (!ops->hierarchies)
return true;
- if (!handler || !handler->conf)
+ if (!conf)
return ret_set_errno(false, EINVAL);
if ((type & LXC_AUTO_CGROUP_MASK) == 0)
}
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
* 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,
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);
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\"");
}
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);
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 */