Commit 9b8a2067 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

restore: restore sid of task which isn't leaders and isn't a child of init (v4)

It's sign, that a parent has been changed sid after forking a child.
We should know a sid with which a process was born, because in a processes
chain, more then one process might change SID.

v2: fix names of variables
v3: prevent rewriting of born_sid
v4: Abort the restorer with error message if a born_sid can't be determing.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 2c412fa6
......@@ -901,6 +901,7 @@ struct pstree_item *__alloc_pstree_item(bool rst)
item->nr_threads = 0;
item->pid.virt = -1;
item->pid.real = -1;
item->born_sid = -1;
return item;
}
......
......@@ -225,8 +225,33 @@ static int prepare_pstree_ids(void)
if (item->state == TASK_HELPER)
continue;
if (item->sid != item->pid.virt)
if (item->sid != item->pid.virt) {
struct pstree_item *parent;
if (item->parent->sid == item->sid)
continue;
/* the task could fork a child before and after setsid() */
parent = item->parent;
while (parent && parent->pid.virt != item->sid) {
if (parent->born_sid != -1 && parent->born_sid != item->sid) {
pr_err("Can't determing with which sid (%d or %d)"
"the process %d was born\n",
parent->born_sid, item->sid, parent->pid.virt);
return -1;
}
parent->born_sid = item->sid;
pr_info("%d was born with sid %d\n", parent->pid.virt, item->sid);
parent = parent->parent;
}
if (parent == NULL) {
pr_err("Can't find a session leader for %d\n", item->sid);
return -1;
}
continue;
}
pr_info("Session leader %d\n", item->sid);
......@@ -783,6 +808,16 @@ static void restore_pgid(void)
static char proc_mountpoint[PATH_MAX] = "/proc";
static bool restore_before_setsid(struct pstree_item *child)
{
int csid = child->born_sid == -1 ? child->sid : child->born_sid;
if (child->parent->born_sid == csid)
return true;
return false;
}
static int restore_task_with_children(void *_arg)
{
struct cr_clone_arg *ca = _arg;
......@@ -820,8 +855,6 @@ static int restore_task_with_children(void *_arg)
exit(-1);
}
restore_sid();
/*
* The block mask will be restored in sigresturn.
*
......@@ -837,13 +870,31 @@ static int restore_task_with_children(void *_arg)
pr_info("Restoring children:\n");
list_for_each_entry(child, &me->children, list) {
if (!restore_before_setsid(child))
continue;
BUG_ON(child->born_sid != -1 && getsid(getpid()) != child->born_sid);
ret = fork_with_pid(child, 0);
if (ret < 0)
exit(1);
}
futex_dec_and_wake(&task_entries->nr_in_progress);
futex_wait_while(&task_entries->start, CR_STATE_FORKING);
restore_sid();
pr_info("Restoring children:\n");
list_for_each_entry(child, &me->children, list) {
if (restore_before_setsid(child))
continue;
ret = fork_with_pid(child, 0);
if (ret < 0)
exit(1);
}
if (me->state != TASK_HELPER) {
futex_dec_and_wake(&task_entries->nr_in_progress);
futex_wait_while(&task_entries->start, CR_STATE_FORKING);
}
restore_pgid();
......
......@@ -189,6 +189,7 @@ struct pstree_item {
struct list_head children; /* array of children */
pid_t pgid;
pid_t sid;
pid_t born_sid;
int state; /* TASK_XXX constants */
int nr_threads; /* number of threads */
struct pid *threads; /* array of threads */
......
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