mirror of
git://github.com/lxc/lxc
synced 2025-08-31 15:19:26 +00:00
Merge pull request #3916 from brauner/2021-07-29.fixes
conf: move remaining setup before pivot root
This commit is contained in:
@@ -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");
|
||||
|
@@ -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,
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user