linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kthread: fix use-after-free if kthread fork fails
@ 2017-05-05 16:20 Vegard Nossum
  2017-05-05 16:44 ` Oleg Nesterov
  0 siblings, 1 reply; 4+ messages in thread
From: Vegard Nossum @ 2017-05-05 16:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, Frederic Weisbecker, Jamie Iles,
	Vegard Nossum, Oleg Nesterov, Peter Zijlstra, Thomas Gleixner,
	Andy Lutomirski

If a kthread forks (e.g. usermodehelper since commit 1da5c46fa965) but
fails in copy_process() between calling dup_task_struct() and setting
p->set_child_tid, then the value of p->set_child_tid will be inherited
from the parent and get prematurely freed by free_kthread_struct().

    kthread()
     - worker_thread()
        - process_one_work()
        |  - call_usermodehelper_exec_work()
        |     - kernel_thread()
        |        - _do_fork()
        |           - copy_process()
        |              - dup_task_struct()
        |                 - arch_dup_task_struct()
        |                    - tsk->set_child_tid = current->set_child_tid // implied
        |              - ...
        |              - goto bad_fork_*
        |              - ...
        |              - free_task(tsk)
        |                 - free_kthread_struct(tsk)
        |                    - kfree(tsk->set_child_tid)
        - ...
        - schedule()
           - __schedule()
              - wq_worker_sleeping()
                 - kthread_data(task)->flags // UAF

The problem started showing up with commit 1da5c46fa965 since it reused
->set_child_tid for the kthread worker data.

A better long-term solution might be to get rid of the ->set_child_tid
abuse. The comment in set_kthread_struct() also looks slightly wrong.

Fixes: 1da5c46fa965ff90f5ffc080b6ab3fae5e227bc3 ("kthread: Make struct kthread kmalloc'ed")
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Debugged-by: Jamie Iles <jamie.iles@oracle.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
---
 kernel/fork.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/fork.c b/kernel/fork.c
index dd5a371c392a..fbdc29365b83 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -518,6 +518,13 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 	atomic_set(&tsk->stack_refcount, 1);
 #endif
 
+	/*
+	 * Forking kthreads (e.g. usermodehelper) should not inherit this
+	 * field since it's a pointer to a 'struct kthread' which is not
+	 * reference counted.
+	 */
+	tsk->set_child_tid = NULL;
+
 	if (err)
 		goto free_stack;
 
-- 
2.12.0.rc0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-05-06 19:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-05 16:20 [PATCH] kthread: fix use-after-free if kthread fork fails Vegard Nossum
2017-05-05 16:44 ` Oleg Nesterov
2017-05-05 17:17   ` Vegard Nossum
2017-05-06 19:51     ` Oleg Nesterov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).