From 7c0c0745980ec91366251886c1266c3f30d50642 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 7 Feb 2017 11:43:29 +0300 Subject: [PATCH] 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. Signed-off-by: Andrei Vagin --- criu/cr-restore.c | 29 +++++++++++++---- criu/filesystems.c | 2 ++ criu/include/tty.h | 3 ++ criu/tty.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 9fa9bc3b26..911d7af7c6 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -77,6 +77,7 @@ #include "fault-injection.h" #include "sk-queue.h" #include "sigframe.h" +#include "fdstore.h" #include "parasite-syscall.h" #include "files-reg.h" @@ -174,9 +175,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, @@ -186,6 +184,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); @@ -226,9 +231,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; @@ -1399,6 +1401,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; @@ -1415,6 +1424,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; @@ -3197,6 +3213,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(); diff --git a/criu/filesystems.c b/criu/filesystems.c index 7fc4c26220..4688d1f5fc 100644 --- a/criu/filesystems.c +++ b/criu/filesystems.c @@ -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, diff --git a/criu/include/tty.h b/criu/include/tty.h index 6fa00db2c1..4656038fa5 100644 --- a/criu/include/tty.h +++ b/criu/include/tty.h @@ -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); diff --git a/criu/tty.c b/criu/tty.c index 5bfce440b3..c1bb95c6a7 100644 --- a/criu/tty.c +++ b/criu/tty.c @@ -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; +}