diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-27 17:52:27 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-27 17:52:27 +0200 |
commit | d024baa58a4a7e5eb6058017771d15b9e47b56db (patch) | |
tree | 03e0a3338ecc033942c48acf51bac9138ef0dfd6 /kernel/fork.c | |
parent | Merge tag 'trace-v4.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | kthread: Fix use-after-free if kthread fork fails (diff) | |
download | linux-d024baa58a4a7e5eb6058017771d15b9e47b56db.tar.xz linux-d024baa58a4a7e5eb6058017771d15b9e47b56db.zip |
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull kthread fix from Thomas Gleixner:
"A single fix which prevents a use after free when kthread fork fails"
* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
kthread: Fix use-after-free if kthread fork fails
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index aa1076c5e4a9..e53770d2bf95 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1577,6 +1577,18 @@ static __latent_entropy struct task_struct *copy_process( if (!p) goto fork_out; + /* + * This _must_ happen before we call free_task(), i.e. before we jump + * to any of the bad_fork_* labels. This is to avoid freeing + * p->set_child_tid which is (ab)used as a kthread's data pointer for + * kernel threads (PF_KTHREAD). + */ + p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; + /* + * Clear TID on mm_release()? + */ + p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; + ftrace_graph_init_task(p); rt_mutex_init_task(p); @@ -1743,11 +1755,6 @@ static __latent_entropy struct task_struct *copy_process( } } - p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; - /* - * Clear TID on mm_release()? - */ - p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; #ifdef CONFIG_BLOCK p->plug = NULL; #endif |