diff --git a/src/lxc/conf.c b/src/lxc/conf.c index a20d1f073..8dcfc60f3 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1089,7 +1089,7 @@ static int lxc_allocate_ttys(struct lxc_conf *conf) void lxc_delete_tty(struct lxc_tty_info *ttys) { - if (!ttys->tty) + if (!ttys || !ttys->tty) return; for (int i = 0; i < ttys->max; i++) { @@ -1742,7 +1742,9 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) for (ret = -1, opts = mntopt_sets; opts && *opts; opts++) { /* mount new devpts instance */ - ret = mount_beneath_fd(rootfs->dfd_dev, "", "pts", "devpts", MS_NOSUID | MS_NOEXEC, *opts); + ret = mount_at(rootfs->dfd_dev, "", 0, + rootfs->dfd_dev, "pts", PROTECT_LOOKUP_BENEATH, + "devpts", MS_NOSUID | MS_NOEXEC, *opts); if (ret == 0) break; } @@ -1775,7 +1777,9 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) DEBUG("Created \"/dev/ptmx\" file as bind mount target"); /* Main option: use a bind-mount to please AppArmor */ - ret = mount_beneath_fd(rootfs->dfd_dev, "pts/ptmx", "ptmx", NULL, MS_BIND, NULL); + ret = mount_at(rootfs->dfd_dev, "pts/ptmx", (PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS & ~RESOLVE_NO_XDEV), + rootfs->dfd_dev, "ptmx", (PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS & ~RESOLVE_NO_XDEV), + NULL, MS_BIND, NULL); if (!ret) return log_debug(0, "Bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\""); else @@ -3026,7 +3030,7 @@ static int lxc_idmapped_mounts_child(struct lxc_handler *handler) out: ret = lxc_abstract_unix_send_credential(handler->data_sock[0], NULL, 0); if (ret < 0) - return syserror("Failed to inform child that we are done setting up mounts"); + return syserror("Failed to inform parent that we are done setting up mounts"); return fret; } @@ -4055,40 +4059,45 @@ int lxc_idmapped_mounts_parent(struct lxc_handler *handler) static int lxc_recv_ttys_from_child(struct lxc_handler *handler) { - int i; - struct lxc_terminal_info *tty; - int ret = -1; + call_cleaner(lxc_delete_tty) struct lxc_tty_info *info_new = &(struct lxc_tty_info){}; int sock = handler->data_sock[1]; struct lxc_conf *conf = handler->conf; - struct lxc_tty_info *ttys = &conf->ttys; + struct lxc_tty_info *tty_info = &conf->ttys; + size_t ttys_max = tty_info->max; + struct lxc_terminal_info *terminal_info; + int ret; - if (!conf->ttys.max) + if (!ttys_max) return 0; - ttys->tty = malloc(sizeof(*ttys->tty) * ttys->max); - if (!ttys->tty) - return -1; + info_new->tty = malloc(sizeof(*(info_new->tty)) * ttys_max); + if (!info_new->tty) + return ret_errno(ENOMEM); - for (i = 0; i < conf->ttys.max; i++) { - int ttyx = -EBADF, ttyy = -EBADF; - - ret = lxc_abstract_unix_recv_two_fds(sock, &ttyx, &ttyy); - if (ret < 0) - break; - - tty = &ttys->tty[i]; - tty->busy = -1; - tty->ptx = ttyx; - tty->pty = ttyy; - TRACE("Received pty with ptx fd %d and pty fd %d from child", tty->ptx, tty->pty); + for (int i = 0; i < ttys_max; i++) { + terminal_info = &info_new->tty[i]; + terminal_info->busy = -1; + terminal_info->ptx = -EBADF; + terminal_info->pty = -EBADF; } - if (ret < 0) - SYSERROR("Failed to receive %zu ttys from child", ttys->max); - else - TRACE("Received %zu ttys from child", ttys->max); + for (int i = 0; i < ttys_max; i++) { + int ptx = -EBADF, pty = -EBADF; - return ret; + ret = lxc_abstract_unix_recv_two_fds(sock, &ptx, &pty); + if (ret < 0) + return syserror("Failed to receive %zu ttys from child", ttys_max); + + terminal_info = &info_new->tty[i]; + terminal_info->ptx = ptx; + terminal_info->pty = pty; + TRACE("Received pty with ptx fd %d and pty fd %d from child", + terminal_info->ptx, terminal_info->pty); + } + + tty_info->tty = move_ptr(info_new->tty); + TRACE("Received %zu ttys from child", ttys_max); + return 0; } static int lxc_send_console_to_parent(struct lxc_handler *handler) diff --git a/src/lxc/mount_utils.c b/src/lxc/mount_utils.c index 77498bbf3..783503aae 100644 --- a/src/lxc/mount_utils.c +++ b/src/lxc/mount_utils.c @@ -606,66 +606,56 @@ bool can_use_bind_mounts(void) return supported == 1; } -int mount_beneath_fd(int fd, const char *source, const char *target, - const char *fs_name, unsigned int flags, const void *data) +int mount_at(int dfd_from, const char *path_from, __u64 resolve_flags_from, + int dfd_to, const char *path_to, __u64 resolve_flags_to, + const char *fs_name, unsigned int flags, const void *data) { - int ret; - char buf_source[PATH_MAX], buf_target[PATH_MAX]; + __do_close int __fd_from = -EBADF, __fd_to = -EBADF; + char *from = NULL, *to = NULL; + int fd_from, fd_to, ret; + char buf_from[LXC_PROC_SELF_FD_LEN], buf_to[LXC_PROC_SELF_FD_LEN]; - if (abspath(source) || abspath(target)) + if (dfd_from < 0 && !abspath(path_from)) return ret_errno(EINVAL); - ret = strnprintf(buf_target, sizeof(buf_target), "/proc/self/fd/%d/%s", fd, target); - if (ret < 0) - return syserror("Failed to create path"); + if (dfd_to < 0 && !abspath(path_to)) + return ret_errno(EINVAL); - if (is_empty_string(source)) { - ret = mount(fs_name ?: "", buf_target, fs_name, flags, data); + if (!is_empty_string(path_from)) { + __fd_from = open_at(dfd_from, path_from, PROTECT_OPATH_FILE, resolve_flags_from, 0); + if (__fd_from < 0) + return -errno; + fd_from = __fd_from; } else { - ret = strnprintf(buf_source, sizeof(buf_source), "/proc/self/fd/%d/%s", fd, source); + fd_from = dfd_from; + } + if (fd_from >= 0) { + ret = strnprintf(buf_from, sizeof(buf_from), "/proc/self/fd/%d", fd_from); if (ret < 0) return syserror("Failed to create path"); - - source = buf_source; - ret = mount(source, buf_target, fs_name, flags, data); + from = buf_from; } - if (ret < 0) - return syserror("Failed to mount \"%s\" to \"%s\"", source, buf_target); - TRACE("Mounted \"%s\" to \"%s\"", source, buf_target); - return 0; -} - -int mount_fd(int fd_source, int fd_target, const char *fs_name, - unsigned int flags, const void *data) -{ - int ret; - char buf_source[LXC_PROC_PID_FD_LEN], buf_target[LXC_PROC_PID_FD_LEN]; - char *source = buf_source, *target = buf_target; - - if (fd_source < 0) { - source = NULL; + if (!is_empty_string(path_to)) { + __fd_to = open_at(dfd_to, path_to, PROTECT_OPATH_FILE, resolve_flags_to, 0); + if (__fd_to < 0) + return -errno; + fd_to = __fd_to; } else { - ret = strnprintf(buf_source, sizeof(buf_source), - "/proc/self/fd/%d", fd_source); + fd_to = dfd_to; + } + if (fd_to >= 0) { + ret = strnprintf(buf_to, sizeof(buf_to), "/proc/self/fd/%d", fd_to); if (ret < 0) - return ret; + return syserror("Failed to create path"); + to = buf_to; } - if (fd_target < 0) { - target = NULL; - } else { - ret = strnprintf(buf_target, sizeof(buf_target), - "/proc/self/fd/%d", fd_target); - if (ret < 0) - return ret; - } - - ret = mount(source, target, "none", MS_BIND, 0); + ret = mount(from ?: fs_name, to, fs_name, flags, data); if (ret < 0) return syserror("Failed to mount \"%s\" to \"%s\"", - maybe_empty(source), maybe_empty(target)); + maybe_empty(from), maybe_empty(to)); - TRACE("Mounted \"%s\" to \"%s\"", maybe_empty(source), maybe_empty(target)); + TRACE("Mounted \"%s\" to \"%s\"", maybe_empty(from), maybe_empty(to)); return 0; } diff --git a/src/lxc/mount_utils.h b/src/lxc/mount_utils.h index 4caf34b2f..6fed1a0a9 100644 --- a/src/lxc/mount_utils.h +++ b/src/lxc/mount_utils.h @@ -221,10 +221,15 @@ __hidden extern unsigned long add_required_remount_flags(const char *s, __hidden extern bool can_use_mount_api(void); __hidden extern bool can_use_bind_mounts(void); -__hidden extern int mount_beneath_fd(int fd, const char *source, - const char *target, const char *fs_name, - unsigned int flags, const void *data); -__hidden extern int mount_fd(int fd_source, int fd_target, const char *fs_name, - unsigned int flags, const void *data); +__hidden extern int mount_at(int dfd_from, const char *path_from, + __u64 resolve_flags_from, int dfd_to, + const char *path_to, __u64 resolve_flags_to, + const char *fs_name, unsigned int flags, + const void *data); +static inline int mount_fd(int fd_from, int fd_to, const char *fs_name, + unsigned int flags, const void *data) +{ + return mount_at(fd_from, "", 0, fd_to, "", 0, fs_name, flags, data); +} #endif /* __LXC_MOUNT_UTILS_H */