Skip to content

Commit

Permalink
Merge pull request #3653 from brauner/2021-02-04/lxc-4.0.6-cgroup-mou…
Browse files Browse the repository at this point in the history
…nt-fix

cgroups: fix cgroup mounting
  • Loading branch information
stgraber committed Feb 4, 2021
2 parents 252605b + 8cfda41 commit 80d4adf
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 16 deletions.
21 changes: 11 additions & 10 deletions src/lxc/cgroups/cgfsng.c
Expand Up @@ -44,6 +44,7 @@
#include "mainloop.h"
#include "memory_utils.h"
#include "storage/storage.h"
#include "syscall_wrappers.h"
#include "utils.h"

#ifndef HAVE_STRLCPY
Expand Down Expand Up @@ -1801,11 +1802,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)
Expand All @@ -1814,7 +1816,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)
Expand All @@ -1826,7 +1828,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
Expand Down Expand Up @@ -1870,16 +1872,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,
Expand Down
3 changes: 1 addition & 2 deletions src/lxc/cgroups/cgroup.h
Expand Up @@ -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);
Expand Down
5 changes: 1 addition & 4 deletions src/lxc/conf.c
Expand Up @@ -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\"");
}

Expand Down
19 changes: 19 additions & 0 deletions src/lxc/syscall_wrappers.h
Expand Up @@ -254,6 +254,25 @@ struct lxc_open_how {
(similar to chroot(2)). */
#endif

#define PROTECT_LOOKUP_BENEATH (RESOLVE_BENEATH | RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS (PROTECT_LOOKUP_BENEATH & ~RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS (PROTECT_LOOKUP_BENEATH & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS))
#define PROTECT_LOOKUP_BENEATH_XDEV (PROTECT_LOOKUP_BENEATH & ~RESOLVE_NO_XDEV)

#define PROTECT_LOOKUP_ABSOLUTE (PROTECT_LOOKUP_BENEATH & ~RESOLVE_BENEATH)
#define PROTECT_LOOKUP_ABSOLUTE_WITH_SYMLINKS (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_ABSOLUTE_WITH_MAGICLINKS (PROTECT_LOOKUP_ABSOLUTE & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS))
#define PROTECT_LOOKUP_ABSOLUTE_XDEV (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_XDEV)

#define PROTECT_OPATH_FILE (O_NOFOLLOW | O_PATH | O_CLOEXEC)
#define PROTECT_OPATH_DIRECTORY (PROTECT_OPATH_FILE | O_DIRECTORY)

#define PROTECT_OPEN_WITH_TRAILING_SYMLINKS (O_CLOEXEC | O_NOCTTY | O_RDONLY)
#define PROTECT_OPEN (PROTECT_OPEN_WITH_TRAILING_SYMLINKS | O_NOFOLLOW)

#define PROTECT_OPEN_W_WITH_TRAILING_SYMLINKS (O_CLOEXEC | O_NOCTTY | O_WRONLY)
#define PROTECT_OPEN_W (PROTECT_OPEN_WITH_TRAILING_SYMLINKS | O_NOFOLLOW)

#ifndef HAVE_OPENAT2
static inline int openat2(int dfd, const char *filename, struct lxc_open_how *how, size_t size)
{
Expand Down
52 changes: 52 additions & 0 deletions src/lxc/utils.c
Expand Up @@ -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_under_dfd, dst_buf, fstype, mnt_flags, data);
else
ret = mount(NULL, dst_buf, fstype, mnt_flags, data);

return ret;
}

/*
* Mount a proc under @rootfs if proc self points to a pid other than
* my own. This is needed to have a known-good proc mount for setting
Expand Down
4 changes: 4 additions & 0 deletions src/lxc/utils.h
Expand Up @@ -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 */

0 comments on commit 80d4adf

Please sign in to comment.