From: Christian Brauner Date: Mon, 4 May 2020 11:26:43 +0000 (+0200) Subject: conf: support console setup on containers without rootfs X-Git-Tag: lxc-5.0.0~442^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf68ffd9e2fce0a33d179aab9b47609f98fd9120;p=thirdparty%2Flxc.git conf: support console setup on containers without rootfs This depends on the new mount api. Closes #3164. Signed-off-by: Christian Brauner --- diff --git a/configure.ac b/configure.ac index 6f1117c10..d9365ac02 100644 --- a/configure.ac +++ b/configure.ac @@ -622,7 +622,7 @@ 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]) +AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree]) # Check for strerror_r() support. Defines: # - HAVE_STRERROR_R if available diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 90d464f68..3753fd7a6 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1576,7 +1576,8 @@ static int setup_personality(int persona) } static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, - const struct lxc_terminal *console) + const struct lxc_terminal *console, + int pts_mnt_fd) { int ret; char path[PATH_MAX]; @@ -1589,7 +1590,8 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, if (ret < 0 || (size_t)ret >= sizeof(path)) return -1; - /* When we are asked to setup a console we remove any previous + /* + * When we are asked to setup a console we remove any previous * /dev/console bind-mounts. */ if (file_exists(path)) { @@ -1600,7 +1602,8 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path); } - /* For unprivileged containers autodev or automounts will already have + /* + * For unprivileged containers autodev or automounts will already have * taken care of creating /dev/console. */ ret = mknod(path, S_IFREG | 0000, 0); @@ -1611,17 +1614,20 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, if (ret < 0) return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name); - ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path); + if (pts_mnt_fd >= 0) + ret = move_mount(pts_mnt_fd, "", -EBADF, path, MOVE_MOUNT_F_EMPTY_PATH); + else + ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path); if (ret < 0) - return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, path); + return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pts_mnt_fd, console->name, path); - DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path); + DEBUG("Mounted pts device %d(%s) onto \"%s\"", pts_mnt_fd, console->name, path); return 0; } static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, const struct lxc_terminal *console, - char *ttydir) + char *ttydir, int pts_mnt_fd) { int ret; char path[PATH_MAX], lxcpath[PATH_MAX]; @@ -1669,9 +1675,12 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name); /* bind mount console->name to '/dev//console' */ - ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); + if (pts_mnt_fd >= 0) + ret = move_mount(pts_mnt_fd, "", -EBADF, path, MOVE_MOUNT_F_EMPTY_PATH); + else + ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); if (ret < 0) - return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); + return log_error_errno(-1, errno, "Failed to mount %d(%s) on \"%s\"", pts_mnt_fd, console->name, lxcpath); DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); /* bind mount '/dev//console' to '/dev/console' */ @@ -1685,13 +1694,14 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, } static int lxc_setup_console(const struct lxc_rootfs *rootfs, - const struct lxc_terminal *console, char *ttydir) + const struct lxc_terminal *console, char *ttydir, + int pts_mnt_fd) { if (!ttydir) - return lxc_setup_dev_console(rootfs, console); + return lxc_setup_dev_console(rootfs, console, pts_mnt_fd); - return lxc_setup_ttydir_console(rootfs, console, ttydir); + return lxc_setup_ttydir_console(rootfs, console, ttydir, pts_mnt_fd); } static int parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size) @@ -3267,6 +3277,7 @@ static int lxc_setup_boot_id(void) int lxc_setup(struct lxc_handler *handler) { + __do_close int pts_mnt_fd = -EBADF; int ret; const char *lxcpath = handler->lxcpath, *name = handler->name; struct lxc_conf *lxc_conf = handler->conf; @@ -3305,6 +3316,12 @@ int lxc_setup(struct lxc_handler *handler) return log_error(-1, "Failed to send network device names and ifindices to parent"); } + pts_mnt_fd = open_tree(-EBADF, lxc_conf->console.name, + OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_EMPTY_PATH); + if (pts_mnt_fd < 0) + SYSTRACE("Failed to create detached mount for container's console \"%s\"", + lxc_conf->console.name); + if (lxc_conf->autodev > 0) { ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath); if (ret < 0) @@ -3377,8 +3394,12 @@ int lxc_setup(struct lxc_handler *handler) if (!verify_start_hooks(lxc_conf)) return log_error(-1, "Failed to verify start hooks"); + ret = lxc_create_tmp_proc_mount(lxc_conf); + if (ret < 0) + return log_error(-1, "Failed to \"/proc\" LSMs"); + ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, - lxc_conf->ttys.dir); + lxc_conf->ttys.dir, pts_mnt_fd); if (ret < 0) return log_error(-1, "Failed to setup console"); @@ -3386,10 +3407,6 @@ int lxc_setup(struct lxc_handler *handler) if (ret < 0) return log_error(-1, "Failed to setup \"/dev\" symlinks"); - ret = lxc_create_tmp_proc_mount(lxc_conf); - if (ret < 0) - return log_error(-1, "Failed to \"/proc\" LSMs"); - ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs); if (ret < 0) return log_error(-1, "Failed to pivot root into rootfs"); @@ -4476,8 +4493,8 @@ int userns_exec_mapped_root(const char *path, int path_fd, if (!gid_valid(container_host_gid)) return log_error(-1, "No gid mapping for container root"); - if (path) { - fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY); + if (path_fd < 0) { + fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_PATH); if (fd < 0) return log_error_errno(-errno, errno, "Failed to open \"%s\"", path); target_fd = fd; diff --git a/src/lxc/macro.h b/src/lxc/macro.h index 3df19d6d3..3a5bb0746 100644 --- a/src/lxc/macro.h +++ b/src/lxc/macro.h @@ -57,6 +57,20 @@ #define CAP_SETGID 6 #endif +/* move_mount */ +#ifndef MOVE_MOUNT_F_EMPTY_PATH +#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ +#endif + +/* open_tree */ +#ifndef OPEN_TREE_CLONE +#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ +#endif + +#ifndef OPEN_TREE_CLOEXEC +#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ +#endif + /* prctl */ #ifndef PR_CAPBSET_READ #define PR_CAPBSET_READ 23 diff --git a/src/lxc/syscall_numbers.h b/src/lxc/syscall_numbers.h index 94bac859a..e7a9dd9a4 100644 --- a/src/lxc/syscall_numbers.h +++ b/src/lxc/syscall_numbers.h @@ -501,4 +501,40 @@ #endif #endif +#ifndef __NR_move_mount + #if defined __alpha__ + #define __NR_move_mount 539 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_move_mount 4429 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_move_mount 6429 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_move_mount 5429 + #endif + #else + #define __NR_move_mount 429 + #endif +#endif + +#ifndef __NR_open_tree + #if defined __alpha__ + #define __NR_open_tree 538 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_open_tree 4428 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_open_tree 6428 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_open_tree 5428 + #endif + #else + #define __NR_open_tree 428 + #endif +#endif + #endif /* __LXC_SYSCALL_NUMBERS_H */ diff --git a/src/lxc/syscall_wrappers.h b/src/lxc/syscall_wrappers.h index 1cef21585..041daf357 100644 --- a/src/lxc/syscall_wrappers.h +++ b/src/lxc/syscall_wrappers.h @@ -137,4 +137,28 @@ static int faccessat(int __fd, const char *__file, int __type, int __flag) } #endif +#ifndef HAVE_MOVE_MOUNT +static inline int move_mount_lxc(int from_dfd, const char *from_pathname, + int to_dfd, const char *to_pathname, + unsigned int flags) +{ + return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, + to_pathname, flags); +} +#define move_mount move_mount_lxc +#else +extern int move_mount(int from_dfd, const char *from_pathname, int to_dfd, + const char *to_pathname, unsigned int flags); +#endif + +#ifndef HAVE_OPEN_TREE +static inline int open_tree_lxc(int dfd, const char *filename, unsigned int flags) +{ + return syscall(__NR_open_tree, dfd, filename, flags); +} +#define open_tree open_tree_lxc +#else +extern int open_tree(int dfd, const char *filename, unsigned int flags); +#endif + #endif /* __LXC_SYSCALL_WRAPPER_H */