Commit 475bb1e7 authored by Pavel Emelyanov's avatar Pavel Emelyanov

rst: Evaluate per-task clone mask early

When we've read all pstree-items and their ids we
can get the desired clone-flags early and avoid all
these dances with flag calculations in fork_with_pid
and company.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 10b338c5
......@@ -799,19 +799,17 @@ static void write_pidfile(char *pfname, int pid)
close(fd);
}
static inline int fork_with_pid(struct pstree_item *item, unsigned long ns_clone_flags)
static inline int fork_with_pid(struct pstree_item *item)
{
int ret = -1;
struct cr_clone_arg ca;
pid_t pid = item->pid.virt;
pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ns_clone_flags);
ca.item = item;
ca.clone_flags = ns_clone_flags;
ca.clone_flags = item->rst->clone_flags;
if (shared_fdtable(item))
ca.clone_flags |= CLONE_FILES;
pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags);
if (!(ca.clone_flags & CLONE_NEWPID)) {
char buf[32];
......@@ -1070,7 +1068,7 @@ static int restore_task_with_children(void *_arg)
BUG_ON(child->born_sid != -1 && getsid(getpid()) != child->born_sid);
ret = fork_with_pid(child, 0);
ret = fork_with_pid(child);
if (ret < 0)
exit(1);
}
......@@ -1081,7 +1079,7 @@ static int restore_task_with_children(void *_arg)
list_for_each_entry(child, &current->children, sibling) {
if (restore_before_setsid(child))
continue;
ret = fork_with_pid(child, 0);
ret = fork_with_pid(child);
if (ret < 0)
exit(1);
}
......@@ -1176,7 +1174,7 @@ static int restore_root_task(struct pstree_item *init, struct cr_options *opts)
futex_set(&task_entries->nr_in_progress, stage_participants(CR_STATE_FORKING));
ret = fork_with_pid(init, current_ns_mask);
ret = fork_with_pid(init);
if (ret < 0)
return -1;
......
......@@ -254,9 +254,11 @@ struct rst_info {
void *premmapped_addr;
unsigned long premmapped_len;
unsigned long clone_flags;
int service_fd_id;
struct fdt *fdt;
};
static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
......
......@@ -22,6 +22,5 @@ struct pstree_item;
int dump_task_ns_ids(struct pstree_item *);
extern unsigned long current_ns_mask;
int check_ns_ids(struct pstree_item *);
#endif /* __CR_NS_H__ */
......@@ -55,6 +55,8 @@ struct robust_list_head;
#define CLONE_NEWNET 0x40000000
#endif
#define CLONE_ALLNS (CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_NEWNS)
#define setns sys_setns
struct rlimit;
......
......@@ -260,56 +260,6 @@ int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
return 0;
}
static unsigned long get_clone_mask(TaskKobjIdsEntry *i,
TaskKobjIdsEntry *p)
{
unsigned long mask = 0;
if (i->pid_ns_id != p->pid_ns_id)
mask |= CLONE_NEWPID;
if (i->net_ns_id != p->net_ns_id)
mask |= CLONE_NEWNET;
if (i->ipc_ns_id != p->ipc_ns_id)
mask |= CLONE_NEWIPC;
if (i->uts_ns_id != p->uts_ns_id)
mask |= CLONE_NEWUTS;
if (i->mnt_ns_id != p->mnt_ns_id)
mask |= CLONE_NEWNS;
return mask;
}
int check_ns_ids(struct pstree_item *item)
{
struct pstree_item *p = item->parent;
if (!p) {
if (!root_ids) {
current_ns_mask = opts.rst_namespaces_flags;
return 0;
}
current_ns_mask = get_clone_mask(item->ids, root_ids);
pr_info("Will restore in %lx namespaces\n", current_ns_mask);
return 0;
}
if (!item->ids)
return 0;
while (!p->ids) {
p = p->parent;
BUG_ON(!p); /* must meet the root_item */
}
if (get_clone_mask(item->ids, p->ids)) {
pr_err("Task in sub namespace\n");
return -1;
}
return 0;
}
int prepare_namespace(int pid, unsigned long clone_flags)
{
pr_info("Restoring namespaces %d flags 0x%lx\n",
......
......@@ -304,7 +304,7 @@ static int prepare_pstree_ids(void)
if (item->sid == root_item->sid || item->sid == item->pid.virt)
continue;
helper = alloc_pstree_item();
helper = alloc_pstree_item_with_rst();
if (helper == NULL)
return -1;
helper->sid = item->sid;
......@@ -422,7 +422,7 @@ static int prepare_pstree_ids(void)
if (current_pgid == item->pgid)
continue;
helper = alloc_pstree_item();
helper = alloc_pstree_item_with_rst();
if (helper == NULL)
return -1;
helper->sid = item->sid;
......@@ -440,6 +440,27 @@ static int prepare_pstree_ids(void)
return 0;
}
static unsigned long get_clone_mask(TaskKobjIdsEntry *i,
TaskKobjIdsEntry *p)
{
unsigned long mask = 0;
if (i->files_id == p->files_id)
mask |= CLONE_FILES;
if (i->pid_ns_id != p->pid_ns_id)
mask |= CLONE_NEWPID;
if (i->net_ns_id != p->net_ns_id)
mask |= CLONE_NEWNET;
if (i->ipc_ns_id != p->ipc_ns_id)
mask |= CLONE_NEWIPC;
if (i->uts_ns_id != p->uts_ns_id)
mask |= CLONE_NEWUTS;
if (i->mnt_ns_id != p->mnt_ns_id)
mask |= CLONE_NEWNS;
return mask;
}
static int prepare_pstree_kobj_ids(void)
{
struct pstree_item *item;
......@@ -447,23 +468,49 @@ static int prepare_pstree_kobj_ids(void)
/* Find a process with minimal pid for shared fd tables */
for_each_pstree_item(item) {
struct pstree_item *parent = item->parent;
TaskKobjIdsEntry *ids;
unsigned long cflags;
if (!item->ids) {
if (item == root_item) {
cflags = opts.rst_namespaces_flags;
goto set_mask;
}
if (item->state == TASK_HELPER)
continue;
}
if (check_ns_ids(item))
return -1;
if (parent)
ids = parent->ids;
else
ids = root_ids;
if (parent == NULL)
continue;
cflags = get_clone_mask(item->ids, ids);
if (shared_fdtable(item)) {
if (cflags & CLONE_FILES) {
int ret;
ret = shared_fdt_prepare(item);
if (ret)
return ret;
}
set_mask:
item->rst->clone_flags = cflags;
/*
* Workaround for current namespaces model --
* all tasks should be in one namespace. And
* this namespace is either inherited from the
* crtools or is created for the init task (only)
*/
if (item == root_item) {
pr_info("Will restore in %lx namespaces\n", cflags);
current_ns_mask = cflags & CLONE_ALLNS;
} else if (cflags & CLONE_ALLNS) {
pr_err("Can't restore sub-task in NS\n");
return -1;
}
}
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