diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 06d759ab4c62..e53770d2bf95 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1577,6 +1577,18 @@ static __latent_entropy struct task_struct *copy_process( | |||
1577 | if (!p) | 1577 | if (!p) |
1578 | goto fork_out; | 1578 | goto fork_out; |
1579 | 1579 | ||
1580 | /* | ||
1581 | * This _must_ happen before we call free_task(), i.e. before we jump | ||
1582 | * to any of the bad_fork_* labels. This is to avoid freeing | ||
1583 | * p->set_child_tid which is (ab)used as a kthread's data pointer for | ||
1584 | * kernel threads (PF_KTHREAD). | ||
1585 | */ | ||
1586 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | ||
1587 | /* | ||
1588 | * Clear TID on mm_release()? | ||
1589 | */ | ||
1590 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; | ||
1591 | |||
1580 | ftrace_graph_init_task(p); | 1592 | ftrace_graph_init_task(p); |
1581 | 1593 | ||
1582 | rt_mutex_init_task(p); | 1594 | rt_mutex_init_task(p); |
@@ -1743,11 +1755,6 @@ static __latent_entropy struct task_struct *copy_process( | |||
1743 | } | 1755 | } |
1744 | } | 1756 | } |
1745 | 1757 | ||
1746 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | ||
1747 | /* | ||
1748 | * Clear TID on mm_release()? | ||
1749 | */ | ||
1750 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; | ||
1751 | #ifdef CONFIG_BLOCK | 1758 | #ifdef CONFIG_BLOCK |
1752 | p->plug = NULL; | 1759 | p->plug = NULL; |
1753 | #endif | 1760 | #endif |
@@ -1845,11 +1852,13 @@ static __latent_entropy struct task_struct *copy_process( | |||
1845 | */ | 1852 | */ |
1846 | recalc_sigpending(); | 1853 | recalc_sigpending(); |
1847 | if (signal_pending(current)) { | 1854 | if (signal_pending(current)) { |
1848 | spin_unlock(¤t->sighand->siglock); | ||
1849 | write_unlock_irq(&tasklist_lock); | ||
1850 | retval = -ERESTARTNOINTR; | 1855 | retval = -ERESTARTNOINTR; |
1851 | goto bad_fork_cancel_cgroup; | 1856 | goto bad_fork_cancel_cgroup; |
1852 | } | 1857 | } |
1858 | if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) { | ||
1859 | retval = -ENOMEM; | ||
1860 | goto bad_fork_cancel_cgroup; | ||
1861 | } | ||
1853 | 1862 | ||
1854 | if (likely(p->pid)) { | 1863 | if (likely(p->pid)) { |
1855 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); | 1864 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); |
@@ -1907,6 +1916,8 @@ static __latent_entropy struct task_struct *copy_process( | |||
1907 | return p; | 1916 | return p; |
1908 | 1917 | ||
1909 | bad_fork_cancel_cgroup: | 1918 | bad_fork_cancel_cgroup: |
1919 | spin_unlock(¤t->sighand->siglock); | ||
1920 | write_unlock_irq(&tasklist_lock); | ||
1910 | cgroup_cancel_fork(p); | 1921 | cgroup_cancel_fork(p); |
1911 | bad_fork_free_pid: | 1922 | bad_fork_free_pid: |
1912 | cgroup_threadgroup_change_end(current); | 1923 | cgroup_threadgroup_change_end(current); |