diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 39bcdb1ee..9e5069239 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -961,6 +961,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) struct lxc_rootfs *rootfs = &conf->rootfs; const struct lxc_tty_info *ttys = &conf->ttys; char *ttydir = ttys->dir; + char tty_source[LXC_PROC_PID_FD_LEN], tty_target[LXC_PROC_PID_FD_LEN]; if (!conf->rootfs.path) return 0; @@ -1002,7 +1003,15 @@ static int lxc_setup_ttys(struct lxc_conf *conf) PROTECT_LOOKUP_BENEATH_XDEV, 0, false); } else { - ret = mount(tty->name, rootfs->buf, "none", MS_BIND, 0); + ret = strnprintf(tty_source, sizeof(tty_source), "/proc/self/fd/%d", tty->pty); + if (ret < 0) + return ret; + + ret = strnprintf(tty_target, sizeof(tty_target), "/proc/self/fd/%d", fd_to); + if (ret < 0) + return ret; + + ret = mount(tty_source, tty_target, "none", MS_BIND, 0); } if (ret < 0) return log_error_errno(-errno, errno, @@ -1037,11 +1046,15 @@ static int lxc_setup_ttys(struct lxc_conf *conf) PROTECT_LOOKUP_BENEATH, 0, false); } else { - ret = strnprintf(rootfs->buf, sizeof(rootfs->buf), "/dev/tty%d", i + 1); + ret = strnprintf(tty_source, sizeof(tty_source), "/proc/self/fd/%d", tty->pty); if (ret < 0) - return ret_errno(-EIO); + return ret; - ret = mount(tty->name, rootfs->buf, "none", MS_BIND, 0); + ret = strnprintf(tty_target, sizeof(tty_target), "/proc/self/fd/%d", fd_to); + if (ret < 0) + return ret; + + ret = mount(tty_source, tty_target, "none", MS_BIND, 0); } if (ret < 0) return log_error_errno(-errno, errno, @@ -1076,33 +1089,12 @@ static int lxc_allocate_ttys(struct lxc_conf *conf) for (size_t i = 0; i < conf->ttys.max; i++) { struct lxc_terminal_info *tty = &ttys->tty[i]; - tty->ptx = -EBADF; - tty->pty = -EBADF; - ret = openpty(&tty->ptx, &tty->pty, NULL, NULL, NULL); + ret = lxc_devpts_terminal(conf->devpts_fd, conf, &tty->ptx, &tty->pty, tty->name); if (ret < 0) { conf->ttys.max = i; - return log_error_errno(-ENOTTY, ENOTTY, "Failed to create tty %zu", i); + return syserror_set(-ENOTTY, "Failed to create tty %zu", i); } - - ret = ttyname_r(tty->pty, tty->name, sizeof(tty->name)); - if (ret < 0) { - conf->ttys.max = i; - return log_error_errno(-ENOTTY, ENOTTY, "Failed to retrieve name of tty %zu pty", i); - } - DEBUG("Created tty with ptx fd %d and pty fd %d", tty->ptx, tty->pty); - - /* Prevent leaking the file descriptors to the container */ - ret = fd_cloexec(tty->ptx, true); - if (ret < 0) - SYSWARN("Failed to set FD_CLOEXEC flag on ptx fd %d of tty device \"%s\"", - tty->ptx, tty->name); - - ret = fd_cloexec(tty->pty, true); - if (ret < 0) - SYSWARN("Failed to set FD_CLOEXEC flag on pty fd %d of tty device \"%s\"", - tty->pty, tty->name); - tty->busy = -1; } @@ -4228,6 +4220,10 @@ int lxc_setup(struct lxc_handler *handler) if (ret < 0) return log_error(-1, "Failed to setup console"); + ret = lxc_create_ttys(handler); + if (ret < 0) + return log_error(-1, "Failed to create ttys"); + ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs); if (ret < 0) return log_error(-1, "Failed to setup \"/dev\" symlinks"); @@ -4240,10 +4236,6 @@ int lxc_setup(struct lxc_handler *handler) if (lxc_conf->autodev > 0) (void)lxc_setup_boot_id(); - ret = lxc_create_ttys(handler); - if (ret < 0) - return -1; - ret = setup_personality(lxc_conf->personality); if (ret < 0) return syserror("Failed to set personality"); diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c index 2f495bc62..312584640 100644 --- a/src/lxc/terminal.c +++ b/src/lxc/terminal.c @@ -909,34 +909,27 @@ err: return -ENODEV; } -static int lxc_terminal_create_native(const char *name, const char *lxcpath, - struct lxc_conf *conf, - struct lxc_terminal *terminal) +int lxc_devpts_terminal(int devpts_fd, struct lxc_conf *conf, + int *ret_ptx, int *ret_pty, char buf[static PATH_MAX]) { - __do_close int devpts_fd = -EBADF, fd_pty = -EBADF; + __do_close int fd_ptx = -EBADF, fd_opath_pty = -EBADF, fd_pty = -EBADF; int pty_nr = -1; int ret; - devpts_fd = lxc_cmd_get_devpts_fd(name, lxcpath); - if (devpts_fd < 0) - return log_error_errno(-1, errno, "Failed to receive devpts fd"); - - terminal->ptx = open_beneath(devpts_fd, "ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC); - if (terminal->ptx < 0) { + fd_ptx = open_beneath(devpts_fd, "ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC); + if (fd_ptx < 0) { if (errno == ENOSPC) return systrace("Exceeded number of allocatable terminals"); return syserror("Failed to open terminal multiplexer device"); } - ret = unlockpt(terminal->ptx); - if (ret < 0) { - SYSWARN("Failed to unlock multiplexer device device"); - goto err; - } + ret = unlockpt(fd_ptx); + if (ret < 0) + return syswarn_set(-ENODEV, "Failed to unlock multiplexer device device"); - terminal->pty = ioctl(terminal->ptx, TIOCGPTPEER, O_RDWR | O_NOCTTY | O_CLOEXEC); - if (terminal->pty < 0) { + fd_pty = ioctl(fd_ptx, TIOCGPTPEER, O_RDWR | O_NOCTTY | O_CLOEXEC); + if (fd_pty < 0) { switch (errno) { case ENOTTY: SYSTRACE("Pure fd-based terminal allocation not possible"); @@ -948,45 +941,54 @@ static int lxc_terminal_create_native(const char *name, const char *lxcpath, SYSWARN("Failed to allocate new pty device"); break; } - goto err; + + return ret_errno(ENODEV); } - ret = ioctl(terminal->ptx, TIOCGPTN, &pty_nr); - if (ret) { - SYSWARN("Failed to retrieve name of terminal pty"); - goto err; - } + ret = ioctl(fd_ptx, TIOCGPTN, &pty_nr); + if (ret) + return syswarn_set(-ENODEV, "Failed to retrieve name of terminal pty"); - fd_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPATH_FILE, - PROTECT_LOOKUP_ABSOLUTE_XDEV, 0); - if (fd_pty < 0) { - SYSWARN("Failed to open terminal pty fd by path %d/%d", devpts_fd, pty_nr); - goto err; - } + fd_opath_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPATH_FILE, + PROTECT_LOOKUP_ABSOLUTE_XDEV, 0); + if (fd_opath_pty < 0) + return syswarn_set(-ENODEV, "Failed to open terminal pty fd by path %d/%d", devpts_fd, pty_nr); - if (!same_file_lax(terminal->pty, fd_pty)) { - SYSWARN("Terminal file descriptor changed"); - goto err; - } + if (!same_file_lax(fd_pty, fd_opath_pty)) + return syswarn_set(-ENODEV, "Terminal file descriptor changed"); - ret = strnprintf(terminal->name, sizeof(terminal->name), "dev/pts/%d", - pty_nr); - if (ret < 0) { - SYSWARN("Failed to create terminal pty name"); - goto err; - } + ret = strnprintf(buf, PATH_MAX, "dev/pts/%d", pty_nr); + if (ret < 0) + return syswarn_set(-ENODEV, "Failed to create terminal pty name"); + + *ret_ptx = move_fd(fd_ptx); + *ret_pty = move_fd(fd_pty); + return 0; +} + +static int lxc_terminal_create_native(const char *name, const char *lxcpath, + struct lxc_conf *conf, + struct lxc_terminal *terminal) +{ + __do_close int devpts_fd = -EBADF; + int ret; + + devpts_fd = lxc_cmd_get_devpts_fd(name, lxcpath); + if (devpts_fd < 0) + return log_error_errno(-1, errno, "Failed to receive devpts fd"); + + ret = lxc_devpts_terminal(devpts_fd, conf, &terminal->ptx, + &terminal->pty, terminal->name); + if (ret < 0) + return ret; ret = lxc_terminal_peer_default(terminal); if (ret < 0) { - SYSWARN("Failed to allocate proxy terminal"); - goto err; + lxc_terminal_delete(terminal); + return syswarn_set(-ENODEV, "Failed to allocate proxy terminal"); } return 0; - -err: - lxc_terminal_delete(terminal); - return -ENODEV; } int lxc_terminal_create(const char *name, const char *lxcpath, diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h index 8bf2bda76..4d2894fe7 100644 --- a/src/lxc/terminal.h +++ b/src/lxc/terminal.h @@ -252,5 +252,8 @@ __hidden extern void lxc_terminal_conf_free(struct lxc_terminal *terminal); __hidden extern void lxc_terminal_info_init(struct lxc_terminal_info *terminal); __hidden extern void lxc_terminal_init(struct lxc_terminal *terminal); __hidden extern int lxc_terminal_signal_sigmask_safe_blocked(struct lxc_terminal *terminal); +__hidden extern int lxc_devpts_terminal(int devpts_fd, struct lxc_conf *conf, + int *ret_ptx, int *ret_pty, + char buf[static PATH_MAX]); #endif /* __LXC_TERMINAL_H */