The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/3513
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 66ac24bff1df0b5107fcd7521aaf5cc299d0059d Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 9 Aug 2020 12:48:02 +0200 Subject: [PATCH 1/3] syscalls: add openat2() Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- configure.ac | 3 +- src/lxc/conf.c | 2 +- src/lxc/syscall_numbers.h | 20 +++++++++++++ src/lxc/syscall_wrappers.h | 57 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 70099e3ad0..f58487f5d0 100644 --- a/configure.ac +++ b/configure.ac @@ -622,7 +622,8 @@ AC_CHECK_HEADER([ifaddrs.h], AC_HEADER_MAJOR # Check for some syscalls functions -AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree execveat clone3 fsopen fspick fsconfig fsmount]) +AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree execveat clone3 fsopen fspick fsconfig fsmount, openat2]) +AC_CHECK_TYPES([struct open_how], [], [], [[#include <linux/openat2.h>]]) AC_CHECK_TYPES([struct clone_args], [], [], [[#include <linux/sched.h>]]) AC_CHECK_MEMBERS([struct clone_args.set_tid],[],[],[[#include <linux/sched.h>]]) AC_CHECK_MEMBERS([struct clone_args.cgroup],[],[],[[#include <linux/sched.h>]]) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 36a2309a43..2e513d1cc7 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1077,7 +1077,7 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, goto reset_umask; } - ret = safe_mount("none", path, "tmpfs", 0, mount_options, + ret = safe_mount("none", "dev", "tmpfs", 0, mount_options, rootfs->path ? rootfs->mount : NULL ); if (ret < 0) { SYSERROR("Failed to mount tmpfs on \"%s\"", path); diff --git a/src/lxc/syscall_numbers.h b/src/lxc/syscall_numbers.h index 72e4ffe460..8305173d6b 100644 --- a/src/lxc/syscall_numbers.h +++ b/src/lxc/syscall_numbers.h @@ -640,4 +640,24 @@ #endif #endif +#ifndef __NR_openat2 + #if defined __alpha__ + #define __NR_openat2 547 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_openat2 4437 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_openat2 6437 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_openat2 5437 + #endif + #elif defined __ia64__ + #define __NR_openat2 (437 + 1024) + #else + #define __NR_openat2 437 + #endif +#endif + #endif /* __LXC_SYSCALL_NUMBERS_H */ diff --git a/src/lxc/syscall_wrappers.h b/src/lxc/syscall_wrappers.h index 6aaa437226..1c1af73f1f 100644 --- a/src/lxc/syscall_wrappers.h +++ b/src/lxc/syscall_wrappers.h @@ -203,4 +203,61 @@ static inline int fsmount_lxc(int fs_fd, unsigned int flags, unsigned int attr_f extern int fsmount(int fs_fd, unsigned int flags, unsigned int attr_flags); #endif +/* + * Arguments for how openat2(2) should open the target path. If only @flags and + * @mode are non-zero, then openat2(2) operates very similarly to openat(2). + * + * However, unlike openat(2), unknown or invalid bits in @flags result in + * -EINVAL rather than being silently ignored. @mode must be zero unless one of + * {O_CREAT, O_TMPFILE} are set. + * + * @flags: O_* flags. + * @mode: O_CREAT/O_TMPFILE file mode. + * @resolve: RESOLVE_* flags. + */ +struct lxc_open_how { + __u64 flags; + __u64 mode; + __u64 resolve; +}; + +/* how->resolve flags for openat2(2). */ +#ifndef RESOLVE_NO_XDEV +#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings + (includes bind-mounts). */ +#endif + +#ifndef RESOLVE_NO_MAGICLINKS +#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style + "magic-links". */ +#endif + +#ifndef RESOLVE_NO_SYMLINKS +#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks + (implies OEXT_NO_MAGICLINKS) */ +#endif + +#ifndef RESOLVE_BENEATH +#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like + "..", symlinks, and absolute + paths which escape the dirfd. */ +#endif + +#ifndef RESOLVE_IN_ROOT +#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".." + be scoped inside the dirfd + (similar to chroot(2)). */ +#endif + +#ifndef HAVE_OPENAT2 +static inline int openat2(int dfd, const char *filename, struct lxc_open_how *how, size_t size) +{ + /* When struct open_how is updated we should update lxc as well. */ +#ifndef HAVE_STRUCT_OPEN_HOW + BUILD_BUG_ON(sizeof(struct lxc_open_how) != sizeof(struct open_how)); +#endif + return syscall(__NR_openat2, dfd, filename, (struct open_how *)how, size); +} +#endif /* HAVE_OPENAT2 */ + #endif /* __LXC_SYSCALL_WRAPPER_H */ From 839314f139190966ec020808c37e48d582815e91 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 9 Aug 2020 15:24:26 +0200 Subject: [PATCH 2/3] utils: add safe_mount_beneath() based on openat2() Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/utils.c | 38 ++++++++++++++++++++++++++++++++++++++ src/lxc/utils.h | 3 +++ 2 files changed, 41 insertions(+) diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 39de189afc..4efed645ff 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1079,6 +1079,44 @@ static int open_without_symlink(const char *target, const char *prefix_skip) return dirfd; } +int safe_mount_beneath(const char *beneath, const char *src, const char *dst, const char *fstype, + unsigned int flags, const void *data) +{ + __do_close int beneath_fd = -EBADF, source_fd = -EBADF, target_fd = -EBADF; + const char *path = beneath ? beneath : "/"; + struct lxc_open_how how = { + .flags = O_RDONLY | O_CLOEXEC | O_PATH, + .resolve = RESOLVE_NO_XDEV | RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS | RESOLVE_BENEATH, + }; + int ret; + char src_buf[LXC_PROC_PID_FD_LEN], tgt_buf[LXC_PROC_PID_FD_LEN]; + + beneath_fd = openat(-1, beneath, O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_PATH); + if (beneath_fd < 0) + return log_error_errno(-errno, errno, "Failed to open %s", path); + + if ((flags & MS_BIND) && src && src[0] != '/') { + source_fd = openat2(beneath_fd, src, &how, sizeof(how)); + if (source_fd < 0) + return -errno; + snprintf(src_buf, sizeof(src_buf), "/proc/self/fd/%d", source_fd); + } else { + src_buf[0] = '\0'; + } + + target_fd = openat2(beneath_fd, dst, &how, sizeof(how)); + if (target_fd < 0) + return -errno; + snprintf(tgt_buf, sizeof(tgt_buf), "/proc/self/fd/%d", target_fd); + + if (!is_empty_string(src_buf)) + ret = mount(src_buf, tgt_buf, fstype, flags, data); + else + ret = mount(src, tgt_buf, fstype, flags, data); + + return ret; +} + /* * Safely mount a path into a container, ensuring that the mount target * is under the container's @rootfs. (If @rootfs is NULL, then the container diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 3f9a409150..b0de9d9abc 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -246,4 +246,7 @@ static inline bool gid_valid(gid_t gid) __hidden extern bool multiply_overflow(int64_t base, uint64_t mult, int64_t *res); +extern int safe_mount_beneath(const char *beneath, const char *src, const char *dst, + const char *fstype, unsigned int flags, const void *data); + #endif /* __LXC_UTILS_H */ From 6c2262f903166a7817b45bb84e76b4f6e4fa10be Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Sun, 9 Aug 2020 15:37:31 +0200 Subject: [PATCH 3/3] conf: switch mount_autodev() to new safe_mount_beneath() helper Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/lxc/conf.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 2e513d1cc7..5fcfb0afa3 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1051,50 +1051,55 @@ static int lxc_create_ttys(struct lxc_handler *handler) static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, int autodevtmpfssize, const char *lxcpath) { - __do_free char *path = NULL; + __do_close int root_mntpt_fd = -EBADF; + const char *path = rootfs->path ? rootfs->mount : NULL; int ret; - size_t clen; mode_t cur_mask; char mount_options[128]; INFO("Preparing \"/dev\""); - /* $(rootfs->mount) + "/dev/pts" + '\0' */ - clen = (rootfs->path ? strlen(rootfs->mount) : 0) + 9; - path = must_realloc(NULL, clen); sprintf(mount_options, "size=%d,mode=755", (autodevtmpfssize != 0) ? autodevtmpfssize : 500000); DEBUG("Using mount options: %s", mount_options); - ret = snprintf(path, clen, "%s/dev", rootfs->path ? rootfs->mount : ""); - if (ret < 0 || (size_t)ret >= clen) - return -1; + root_mntpt_fd = openat(-1, path, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (root_mntpt_fd < 0) + return log_error_errno(-errno, errno, "Failed to open \"%s\"", path); cur_mask = umask(S_IXUSR | S_IXGRP | S_IXOTH); - ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + ret = mkdirat(root_mntpt_fd, "dev" , S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (ret < 0 && errno != EEXIST) { SYSERROR("Failed to create \"/dev\" directory"); ret = -errno; goto reset_umask; } - ret = safe_mount("none", "dev", "tmpfs", 0, mount_options, - rootfs->path ? rootfs->mount : NULL ); + ret = safe_mount_beneath(path, "none", "dev", "tmpfs", 0, mount_options); if (ret < 0) { - SYSERROR("Failed to mount tmpfs on \"%s\"", path); - goto reset_umask; - } - TRACE("Mounted tmpfs on \"%s\"", path); + __do_free char *fallback_path = NULL; - ret = snprintf(path, clen, "%s/dev/pts", rootfs->path ? rootfs->mount : ""); - if (ret < 0 || (size_t)ret >= clen) { - ret = -1; - goto reset_umask; + if (errno != ENOSYS) { + SYSERROR("Failed to mount tmpfs on \"%s\"", path); + goto reset_umask; + } + + if (path) { + fallback_path = must_make_path(path, "/dev", NULL); + ret = safe_mount("none", fallback_path, "tmpfs", 0, mount_options, path); + } 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 we are running on a devtmpfs mapping, dev/pts may already exist. * If not, then create it and exit if that fails... */ - ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + ret = mkdirat(root_mntpt_fd, "dev/pts", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (ret < 0 && errno != EEXIST) { SYSERROR("Failed to create directory \"%s\"", path); ret = -errno;
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel