conf: fd-only tty setup

parent ade356b9
...@@ -806,70 +806,101 @@ static bool append_ttyname(char **pp, char *name) ...@@ -806,70 +806,101 @@ static bool append_ttyname(char **pp, char *name)
static int lxc_setup_ttys(struct lxc_conf *conf) static int lxc_setup_ttys(struct lxc_conf *conf)
{ {
int i, ret; int ret;
struct lxc_rootfs *rootfs = &conf->rootfs;
const struct lxc_tty_info *ttys = &conf->ttys; const struct lxc_tty_info *ttys = &conf->ttys;
char *ttydir = ttys->dir; char *ttydir = ttys->dir;
char path[PATH_MAX], lxcpath[PATH_MAX];
if (!conf->rootfs.path) if (!conf->rootfs.path)
return 0; return 0;
for (i = 0; i < ttys->max; i++) { for (int i = 0; i < ttys->max; i++) {
__do_close int fd_to = -EBADF;
struct lxc_terminal_info *tty = &ttys->tty[i]; struct lxc_terminal_info *tty = &ttys->tty[i];
ret = snprintf(path, sizeof(path), "/dev/tty%d", i + 1);
if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
if (ttydir) { if (ttydir) {
/* create dev/lxc/tty%d" */ char *tty_name, *tty_path;
ret = snprintf(lxcpath, sizeof(lxcpath),
"/dev/%s/tty%d", ttydir, i + 1);
if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
return -1;
ret = mknod(lxcpath, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create \"%s\"", lxcpath);
return -1;
}
ret = unlink(path);
if (ret < 0 && errno != ENOENT) {
SYSERROR("Failed to unlink \"%s\"", path);
return -1;
}
ret = mount(tty->name, lxcpath, "none", MS_BIND, 0); ret = snprintf(rootfs->buf, sizeof(rootfs->buf),
if (ret < 0) { "/dev/%s/tty%d", ttydir, i + 1);
SYSWARN("Failed to bind mount \"%s\" onto \"%s\"", tty->name, lxcpath); if (ret < 0 || (size_t)ret >= sizeof(rootfs->buf))
continue; return ret_errno(-EIO);
tty_path = &rootfs->buf[STRLITERALLEN("/dev/")];
tty_name = tty_path + strlen(ttydir) + 1;
/* create bind-mount target */
fd_to = open_at(rootfs->dfd_dev, tty_path,
PROTECT_OPEN_W | O_CREAT,
PROTECT_LOOKUP_BENEATH, 0);
if (fd_to < 0)
return log_error_errno(-errno, errno,
"Failed to create tty mount target %d(%s)",
rootfs->dfd_dev, tty_path);
ret = unlinkat(rootfs->dfd_dev, tty_name, 0);
if (ret < 0 && errno != ENOENT)
return log_error_errno(-errno, errno,
"Failed to unlink %d(%s)",
rootfs->dfd_dev, tty_name);
if (new_mount_api()) {
ret = fd_bind_mount(tty->pty, "",
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH_XDEV,
fd_to, "",
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH_XDEV, 0,
false);
} else {
ret = mount(tty->name, rootfs->buf, "none", MS_BIND, 0);
} }
DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, lxcpath); if (ret < 0)
return log_error_errno(-errno, errno,
ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", "Failed to bind mount \"%s\" onto \"%s\"",
ttydir, i + 1); tty->name, rootfs->buf);
if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, rootfs->buf);
return -1;
ret = symlink(lxcpath, path); ret = symlinkat(tty_path, rootfs->dfd_dev, tty_name);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to create symlink \"%s\" -> \"%s\"", path, lxcpath); return log_error_errno(-errno, errno,
"Failed to create symlink \"%d(%s)\" -> \"%d(%s)\"",
rootfs->dfd_dev, tty_name,
rootfs->dfd_dev, tty_path);
} else { } else {
/* If we populated /dev, then we need to create ret = snprintf(rootfs->buf, sizeof(rootfs->buf), "tty%d", i + 1);
* /dev/ttyN if (ret < 0 || (size_t)ret >= sizeof(rootfs->buf))
*/ return ret_errno(-EIO);
ret = mknod(path, S_IFREG | 0000, 0);
if (ret < 0) /* this isn't fatal, continue */ /* If we populated /dev, then we need to create /dev/tty<idx>. */
SYSERROR("Failed to create \"%s\"", path); fd_to = open_at(rootfs->dfd_dev, rootfs->buf,
PROTECT_OPEN_W | O_CREAT,
ret = mount(tty->name, path, "none", MS_BIND, 0); PROTECT_LOOKUP_BENEATH, 0);
if (ret < 0) { if (fd_to < 0)
SYSERROR("Failed to mount '%s'->'%s'", tty->name, path); return log_error_errno(-errno, errno,
continue; "Failed to create tty mount target %d(%s)",
rootfs->dfd_dev, rootfs->buf);
if (new_mount_api()) {
ret = fd_bind_mount(tty->pty, "",
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH_XDEV,
fd_to, "",
PROTECT_OPATH_FILE,
PROTECT_LOOKUP_BENEATH, 0,
false);
} else {
ret = snprintf(rootfs->buf, sizeof(rootfs->buf), "/dev/tty%d", i + 1);
if (ret < 0 || (size_t)ret >= sizeof(rootfs->buf))
return ret_errno(-EIO);
ret = mount(tty->name, rootfs->buf, "none", MS_BIND, 0);
} }
if (ret < 0)
DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, path); return log_error_errno(-errno, errno,
"Failed to bind mount \"%s\" onto \"%s\"",
tty->name, rootfs->buf);
DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, rootfs->buf);
} }
if (!append_ttyname(&conf->ttys.tty_names, tty->name)) if (!append_ttyname(&conf->ttys.tty_names, tty->name))
...@@ -880,13 +911,11 @@ static int lxc_setup_ttys(struct lxc_conf *conf) ...@@ -880,13 +911,11 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
return 0; return 0;
} }
define_cleanup_function(struct lxc_tty_info *, lxc_delete_tty);
static int lxc_allocate_ttys(struct lxc_conf *conf) static int lxc_allocate_ttys(struct lxc_conf *conf)
{ {
struct lxc_terminal_info *tty_new = NULL; struct lxc_terminal_info *tty_new = NULL;
int ret; int ret;
call_cleaner(lxc_delete_tty) struct lxc_tty_info *ttys = &conf->ttys; struct lxc_tty_info *ttys = &conf->ttys;
/* no tty in the configuration */ /* no tty in the configuration */
if (ttys->max == 0) if (ttys->max == 0)
...@@ -895,27 +924,25 @@ static int lxc_allocate_ttys(struct lxc_conf *conf) ...@@ -895,27 +924,25 @@ static int lxc_allocate_ttys(struct lxc_conf *conf)
tty_new = malloc(sizeof(struct lxc_terminal_info) * ttys->max); tty_new = malloc(sizeof(struct lxc_terminal_info) * ttys->max);
if (!tty_new) if (!tty_new)
return -ENOMEM; return -ENOMEM;
ttys->tty = tty_new;
for (size_t i = 0; i < ttys->max; i++) { for (size_t i = 0; i < conf->ttys.max; i++) {
struct lxc_terminal_info *tty = &ttys->tty[i]; struct lxc_terminal_info *tty = &tty_new[i];
tty->ptx = -EBADF; tty->ptx = -EBADF;
tty->pty = -EBADF; tty->pty = -EBADF;
ret = openpty(&tty->ptx, &tty->pty, NULL, NULL, NULL); ret = openpty(&tty->ptx, &tty->pty, NULL, NULL, NULL);
if (ret < 0) { if (ret < 0) {
ttys->max = i; conf->ttys.max = i;
return log_error_errno(-ENOTTY, ENOTTY, "Failed to create tty %zu", i); return log_error_errno(-ENOTTY, ENOTTY, "Failed to create tty %zu", i);
} }
ret = ttyname_r(tty->pty, tty->name, sizeof(tty->name)); ret = ttyname_r(tty->pty, tty->name, sizeof(tty->name));
if (ret < 0) { if (ret < 0) {
ttys->max = i; conf->ttys.max = i;
return log_error_errno(-ENOTTY, ENOTTY, "Failed to retrieve name of tty %zu pty", i); return log_error_errno(-ENOTTY, ENOTTY, "Failed to retrieve name of tty %zu pty", i);
} }
DEBUG("Created tty \"%s\" with ptx fd %d and pty fd %d", DEBUG("Created tty with ptx fd %d and pty fd %d", tty->ptx, tty->pty);
tty->name, tty->ptx, tty->pty);
/* Prevent leaking the file descriptors to the container */ /* Prevent leaking the file descriptors to the container */
ret = fd_cloexec(tty->ptx, true); ret = fd_cloexec(tty->ptx, true);
...@@ -932,7 +959,7 @@ static int lxc_allocate_ttys(struct lxc_conf *conf) ...@@ -932,7 +959,7 @@ static int lxc_allocate_ttys(struct lxc_conf *conf)
} }
INFO("Finished creating %zu tty devices", ttys->max); INFO("Finished creating %zu tty devices", ttys->max);
move_ptr(ttys); conf->ttys.tty = move_ptr(tty_new);
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment