Commit aa26237e authored by Andrei Vagin's avatar Andrei Vagin

tty: check that a master of a bind-mounted slave is in the root mntns

Here we check that a master of a bind-mounted slave was opened in the
root mount namespace. The problem is that we restore all mounts in the
root mount namespace. Only when all mounts are restored, we create other
mount namespaces.  So when we are restoring mounts, we can open files
only in the root mount namespace.
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent b6f75771
...@@ -700,6 +700,7 @@ static struct fstype fstypes[] = { ...@@ -700,6 +700,7 @@ static struct fstype fstypes[] = {
.parse = devpts_parse, .parse = devpts_parse,
.code = FSTYPE__DEVPTS, .code = FSTYPE__DEVPTS,
.restore = devpts_restore, .restore = devpts_restore,
.check_bindmount = devpts_check_bindmount,
}, { }, {
.name = "simfs", .name = "simfs",
.code = FSTYPE__SIMFS, .code = FSTYPE__SIMFS,
......
...@@ -13,6 +13,7 @@ struct fstype { ...@@ -13,6 +13,7 @@ struct fstype {
int code; int code;
int (*dump)(struct mount_info *pm); int (*dump)(struct mount_info *pm);
int (*restore)(struct mount_info *pm); int (*restore)(struct mount_info *pm);
int (*check_bindmount)(struct mount_info *pm);
int (*parse)(struct mount_info *pm); int (*parse)(struct mount_info *pm);
int (*collect)(struct mount_info *pm); int (*collect)(struct mount_info *pm);
bool (*sb_equal)(struct mount_info *a, struct mount_info *b); bool (*sb_equal)(struct mount_info *a, struct mount_info *b);
......
...@@ -37,6 +37,8 @@ extern void tty_fini_fds(void); ...@@ -37,6 +37,8 @@ extern void tty_fini_fds(void);
extern int tty_restore_ctl_terminal(struct file_desc *d, int fd); extern int tty_restore_ctl_terminal(struct file_desc *d, int fd);
extern int devpts_check_bindmount(struct mount_info *m);
#define OPT_SHELL_JOB "shell-job" #define OPT_SHELL_JOB "shell-job"
#endif /* __CR_TTY_H__ */ #endif /* __CR_TTY_H__ */
...@@ -1267,6 +1267,10 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img) ...@@ -1267,6 +1267,10 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img)
if (!pm->dumped && dump_one_fs(pm)) if (!pm->dumped && dump_one_fs(pm))
return -1; return -1;
if (!fsroot_mounted(pm) &&
pm->fstype->check_bindmount && pm->fstype->check_bindmount(pm))
return -1;
if (pm->mnt_id == CRTIME_MNT_ID) { if (pm->mnt_id == CRTIME_MNT_ID) {
pr_info("Skip dumping cr-time mountpoint: %s\n", pm->mountpoint); pr_info("Skip dumping cr-time mountpoint: %s\n", pm->mountpoint);
return 0; return 0;
......
...@@ -115,6 +115,7 @@ struct tty_dump_info { ...@@ -115,6 +115,7 @@ struct tty_dump_info {
pid_t sid; pid_t sid;
pid_t pgrp; pid_t pgrp;
int fd; int fd;
int mnt_id;
struct tty_driver *driver; struct tty_driver *driver;
int index; int index;
...@@ -1763,6 +1764,7 @@ static int dump_tty_info(int lfd, u32 id, const struct fd_parms *p, struct tty_d ...@@ -1763,6 +1764,7 @@ static int dump_tty_info(int lfd, u32 id, const struct fd_parms *p, struct tty_d
dinfo->sid = pti->sid; dinfo->sid = pti->sid;
dinfo->pgrp = pti->pgrp; dinfo->pgrp = pti->pgrp;
dinfo->fd = p->fd; dinfo->fd = p->fd;
dinfo->mnt_id = p->mnt_id;
dinfo->driver = driver; dinfo->driver = driver;
dinfo->flags = p->flags; dinfo->flags = p->flags;
...@@ -2190,6 +2192,63 @@ static int pty_create_ptmx_index(int dfd, int index, int flags) ...@@ -2190,6 +2192,63 @@ static int pty_create_ptmx_index(int dfd, int index, int flags)
return 0; return 0;
} }
/*
* Here we check that a master of a bind-mounted slave was opened in the root
* mount namespace. The problem is that we restore all mounts in the root mount
* namespace. Only when all mounts are restored, we create other mount
* namespaces. So when we are restoring mounts, we can open files only in the
* root mount namespace.
*/
int devpts_check_bindmount(struct mount_info *m)
{
struct tty_dump_info *dinfo = NULL;
struct mount_info *master_mp;
int index;
if (strcmp(m->root, "/") == 0 || strcmp(m->root, "/ptmx") == 0)
return 0;
if (sscanf(m->root, "/%d", &index) != 1) {
pr_err("Unable to parse %s", m->root);
return -1;
}
list_for_each_entry(dinfo, &all_ttys, list) {
if (!is_pty(dinfo->driver))
continue;
if (dinfo->driver->subtype != TTY_SUBTYPE_MASTER)
continue;
if (dinfo->index == index)
goto found;
}
if (opts.orphan_pts_master) /* external master */
return 0;
pr_err("Unable to find a master for %s\n", m->root);
return -1;
found:
/* mnt_id isn't reported in fdinfo, so here is only one mntns */
if (dinfo->mnt_id == -1)
return 0;
master_mp = lookup_mnt_id(dinfo->mnt_id);
if (!master_mp) {
pr_err("Unable to find a mount %d\n", dinfo->mnt_id);
return -1;
}
if (master_mp->nsid->type != NS_ROOT) {
pr_err("The master for %s isn't from the root mntns", m->root);
return -1;
}
return 0;
}
/* Restore slave pty-s which have to be bind-mounted to somewhere */ /* Restore slave pty-s which have to be bind-mounted to somewhere */
int devpts_restore(struct mount_info *pm) int devpts_restore(struct mount_info *pm)
{ {
......
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