aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWalter Wu <[email protected]>2021-04-29 23:00:45 -0700
committerLinus Torvalds <[email protected]>2021-04-30 11:20:42 -0700
commit23f61f0fe106da8c9f6a883965439ecc2838f116 (patch)
tree0ef2148e8b44b900cc533872a7fff6a9ea691755
parentfc23c074ef5ab47c2fb0975f70329da93850c6d0 (diff)
kasan: record task_work_add() call stack
Why record task_work_add() call stack? Syzbot reports many use-after-free issues for task_work, see [1]. After seeing the free stack and the current auxiliary stack, we think they are useless, we don't know where the work was registered. This work may be the free call stack, so we miss the root cause and don't solve the use-after-free. Add the task_work_add() call stack into the KASAN auxiliary stack in order to improve KASAN reports. It helps programmers solve use-after-free issues. [1]: https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Walter Wu <[email protected]> Suggested-by: Dmitry Vyukov <[email protected]> Reviewed-by: Dmitry Vyukov <[email protected]> Reviewed-by: Jens Axboe <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Acked-by: Andrey Konovalov <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Matthias Brugger <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r--kernel/task_work.c3
-rw-r--r--mm/kasan/kasan.h2
2 files changed, 4 insertions, 1 deletions
diff --git a/kernel/task_work.c b/kernel/task_work.c
index e9316198c64b..1698fbe6f0e1 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -34,6 +34,9 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
{
struct callback_head *head;
+ /* record the work call stack in order to print it in KASAN reports */
+ kasan_record_aux_stack(work);
+
do {
head = READ_ONCE(task->task_works);
if (unlikely(head == &work_exited))
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 071c456a3579..3820ca54743b 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -163,7 +163,7 @@ struct kasan_alloc_meta {
struct kasan_track alloc_track;
#ifdef CONFIG_KASAN_GENERIC
/*
- * call_rcu() call stack is stored into struct kasan_alloc_meta.
+ * The auxiliary stack is stored into struct kasan_alloc_meta.
* The free stack is stored into struct kasan_free_meta.
*/
depot_stack_handle_t aux_stack[2];