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

Reply via email to