Commit 3cedb618 authored by Andrei Vagin's avatar Andrei Vagin

mount: create a slave pty if it has to be bind-mounted to somewhere

Now we create pty pairs when file descriptors are restored.
The problem is that a slave tty can be bind-mounted to somewhere
and in this case we have to create this pair and hold a master file
descritore before related file descriptors will not be restored.

In this patch, a unix socket is used to hold file descriptros.
And we use SK_PEEK_OFF and MSG_PEEK to get any of them.

travis-ci: success for A few fixes to c/r a docker container with a console (rev3)
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 7dc7030d
......@@ -75,6 +75,7 @@
#include "fault-injection.h"
#include "sk-queue.h"
#include "sigframe.h"
#include "fdstore.h"
#include "parasite-syscall.h"
#include "files-reg.h"
......@@ -169,9 +170,6 @@ static struct collect_image_info *cinfos[] = {
&inotify_mark_cinfo,
&fanotify_cinfo,
&fanotify_mark_cinfo,
&tty_info_cinfo,
&tty_cinfo,
&tty_cdata,
&tunfile_cinfo,
&ext_file_cinfo,
&timerfd_cinfo,
......@@ -181,6 +179,13 @@ static struct collect_image_info *cinfos[] = {
&sk_queues_cinfo,
};
/* These images are requered to restore namespaces */
static struct collect_image_info *before_ns_cinfos[] = {
&tty_info_cinfo, /* Restore devpts content */
&tty_cinfo,
&tty_cdata,
};
struct post_prepare_cb {
struct list_head list;
int (*actor)(void *data);
......@@ -221,9 +226,6 @@ static int root_prepare_shared(void)
pr_info("Preparing info about shared resources\n");
if (prepare_shared_tty())
return -1;
if (prepare_shared_reg_files())
return -1;
......@@ -1284,6 +1286,13 @@ static int restore_task_with_children(void *_arg)
/* Restore root task */
if (current->parent == NULL) {
int i;
if (prepare_shared_tty())
goto err;
if (fdstore_init())
goto err;
if (join_namespaces()) {
pr_perror("Join namespaces failed");
goto err;
......@@ -1300,6 +1309,13 @@ static int restore_task_with_children(void *_arg)
if (mount_proc())
goto err;
for (i = 0; i < ARRAY_SIZE(before_ns_cinfos); i++) {
ret = collect_image(before_ns_cinfos[i]);
if (ret)
return -1;
}
if (prepare_namespace(current, ca->clone_flags))
goto err;
......@@ -3045,6 +3061,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
close_proc();
close_service_fd(ROOT_FD_OFF);
close_service_fd(USERNSD_SK);
close_service_fd(FDSTORE_SK_OFF);
close_service_fd(RPC_SK_OFF);
__gcov_flush();
......
......@@ -18,6 +18,7 @@
#include "autofs.h"
#include "util.h"
#include "fs-magic.h"
#include "tty.h"
#include "images/mnt.pb-c.h"
#include "images/binfmt-misc.pb-c.h"
......@@ -698,6 +699,7 @@ static struct fstype fstypes[] = {
.name = "devpts",
.parse = devpts_parse,
.code = FSTYPE__DEVPTS,
.restore = devpts_restore,
}, {
.name = "simfs",
.code = FSTYPE__SIMFS,
......
......@@ -29,6 +29,9 @@ extern struct collect_image_info tty_cinfo;
extern struct collect_image_info tty_cdata;
extern int prepare_shared_tty(void);
struct mount_info;
extern int devpts_restore(struct mount_info *pm);
extern int tty_prep_fds(void);
extern void tty_fini_fds(void);
......
......@@ -29,6 +29,7 @@
#include "namespaces.h"
#include "external.h"
#include "action-scripts.h"
#include "mount.h"
#include "protobuf.h"
#include "util.h"
......@@ -38,6 +39,7 @@
#include "parasite.h"
#include "pstree.h"
#include "fdstore.h"
#include "tty.h"
/*
......@@ -102,6 +104,8 @@ struct tty_info {
struct tty_info *ctl_tty;
struct tty_info *link;
struct tty_data_entry *tty_data;
int fdstore_id;
};
struct tty_dump_info {
......@@ -616,6 +620,9 @@ static int __pty_open_ptmx_index(int index, int flags,
static int pty_open_ptmx_index(struct file_desc *d, struct tty_info *info, int flags)
{
if (info->fdstore_id >= 0)
return fdstore_get(info->fdstore_id);
return __pty_open_ptmx_index(info->tie->pty->index, flags,
open_tty_reg, d, path_from_reg(d));
}
......@@ -1632,6 +1639,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg, struct cr_img *i)
return -1;
}
info->fdstore_id = -1;
list_add(&info->list, &all_ttys);
return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops);
}
......@@ -2143,3 +2151,75 @@ void tty_fini_fds(void)
{
close_service_fd(SELF_STDIN_OFF);
}
static int open_pty(void *arg, int flags)
{
int dfd = (unsigned long) arg;
/*
* Never set as a control terminal automatically, all
* ctty magic happens only in tty_set_sid().
*/
flags |= O_NOCTTY;
return openat(dfd, "ptmx", flags);
}
/* Create a pty pair and save a master descriptor in fdstore */
static int pty_create_ptmx_index(int dfd, int index, int flags)
{
struct tty_info *info;
int fd, id;
fd = __pty_open_ptmx_index(index, flags, open_pty, (void *)(unsigned long) dfd, "ptmx");
if (fd < 0)
return -1;
id = fdstore_add(fd);
if (id < 0)
return -1;
close(fd);
list_for_each_entry(info, &all_ttys, list) {
if (!is_pty(info->driver))
continue;
if (info->tie->pty->index == index) {
info->fdstore_id = id;
}
}
return 0;
}
/* Restore slave pty-s which have to be bind-mounted to somewhere */
int devpts_restore(struct mount_info *pm)
{
struct mount_info *bm;
int dfd, exit_code = -1;
dfd = open(pm->mountpoint, O_RDONLY);
if (dfd < 0) {
pr_perror("Unable to open %s", pm->mountpoint);
return -1;
}
list_for_each_entry(bm, &pm->mnt_bind, mnt_bind) {
int idx;
struct stat st;
if (sscanf(bm->root, "/%d", &idx) < 1)
continue;
if (fstatat(dfd, bm->root + 1, &st, 0) == 0)
continue;
pr_debug("Create a slave tty %d\n", idx);
if (pty_create_ptmx_index(dfd, idx, O_RDWR))
goto err;
}
exit_code = 0;
err:
close(dfd);
return exit_code;
}
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