function-graph: move initialization of new tasks up in fork
When the function graph tracer is enabled, all new tasks must allocate a ret_stack to place the return address of functions. This is because the function graph tracer will replace the real return address with a call to the tracing of the exit function. This initialization happens in fork, but it happens too late. If fork fails, then it will call free_task and that calls the freeing of this ret_stack. But before initialization happens, the new (failed) task points to its parents ret_stack. If a fork failure happens during the function trace, it would be catastrophic for the parent. Also, there's no need to call ftrace_graph_exit_task from fork, since it is called by free_task which fork calls on failure. [ Impact: prevent crash during failed fork running function graph tracer ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
26c01624a2
commit
f7e8b616ed
@ -982,6 +982,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
if (!p)
|
if (!p)
|
||||||
goto fork_out;
|
goto fork_out;
|
||||||
|
|
||||||
|
ftrace_graph_init_task(p);
|
||||||
|
|
||||||
rt_mutex_init_task(p);
|
rt_mutex_init_task(p);
|
||||||
|
|
||||||
#ifdef CONFIG_PROVE_LOCKING
|
#ifdef CONFIG_PROVE_LOCKING
|
||||||
@ -1131,8 +1133,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ftrace_graph_init_task(p);
|
|
||||||
|
|
||||||
p->pid = pid_nr(pid);
|
p->pid = pid_nr(pid);
|
||||||
p->tgid = p->pid;
|
p->tgid = p->pid;
|
||||||
if (clone_flags & CLONE_THREAD)
|
if (clone_flags & CLONE_THREAD)
|
||||||
@ -1141,7 +1141,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
if (current->nsproxy != p->nsproxy) {
|
if (current->nsproxy != p->nsproxy) {
|
||||||
retval = ns_cgroup_clone(p, pid);
|
retval = ns_cgroup_clone(p, pid);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto bad_fork_free_graph;
|
goto bad_fork_free_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
|
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
|
||||||
@ -1233,7 +1233,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
spin_unlock(¤t->sighand->siglock);
|
spin_unlock(¤t->sighand->siglock);
|
||||||
write_unlock_irq(&tasklist_lock);
|
write_unlock_irq(&tasklist_lock);
|
||||||
retval = -ERESTARTNOINTR;
|
retval = -ERESTARTNOINTR;
|
||||||
goto bad_fork_free_graph;
|
goto bad_fork_free_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clone_flags & CLONE_THREAD) {
|
if (clone_flags & CLONE_THREAD) {
|
||||||
@ -1268,8 +1268,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
cgroup_post_fork(p);
|
cgroup_post_fork(p);
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
bad_fork_free_graph:
|
|
||||||
ftrace_graph_exit_task(p);
|
|
||||||
bad_fork_free_pid:
|
bad_fork_free_pid:
|
||||||
if (pid != &init_struct_pid)
|
if (pid != &init_struct_pid)
|
||||||
free_pid(pid);
|
free_pid(pid);
|
||||||
|
Loading…
Reference in New Issue
Block a user