On Mon, Mar 15, 2021 at 3:00 AM Walter Wu <walter-zh.wu@xxxxxxxxxxxx> wrote: > > Why record task_work_add() call stack? > Syzbot reports many use-after-free issues for task_work, see [1]. > After see the free stack and the current auxiliary stack, we think > they are useless, we don't know where register the work, this work > may be the free call stack, so that we miss the root cause and > don't solve the use-after-free. > > Add task_work_add() call stack into KASAN auxiliary stack in > order to improve KASAN report. It is useful for programmers > to solve use-after-free issues. > > [1]: https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run > > Signed-off-by: Walter Wu <walter-zh.wu@xxxxxxxxxxxx> > Suggested-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx> > Cc: Andrey Ryabinin <ryabinin.a.a@xxxxxxxxx> > Cc: Dmitry Vyukov <dvyukov@xxxxxxxxxx> > Cc: Andrey Konovalov <andreyknvl@xxxxxxxxxx> > Cc: Alexander Potapenko <glider@xxxxxxxxxx> > Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > Cc: Matthias Brugger <matthias.bgg@xxxxxxxxx> > Cc: Jens Axboe <axboe@xxxxxxxxx> > Cc: Oleg Nesterov <oleg@xxxxxxxxxx> > --- > kernel/task_work.c | 3 +++ > mm/kasan/kasan.h | 2 +- > 2 files changed, 4 insertions(+), 1 deletion(-) > > diff --git a/kernel/task_work.c b/kernel/task_work.c > index 9cde961875c0..f255294377da 100644 > --- a/kernel/task_work.c > +++ b/kernel/task_work.c > @@ -55,6 +55,9 @@ int task_work_add(struct task_struct *task, struct callback_head *work, > break; > } > > + /* record the work call stack in order to print it in KASAN reports */ > + kasan_record_aux_stack(work); I think this call should be done _before_ we actually queue the work, because this function may operate on non-current task. Consider, we queue the work, the other task already executes it and triggers use-after-free, now only now we record the stack. Moreover, I think we can trigger use-after-free here ourselves while recording the aux stack. We queued the work, and the work can cause own free, so it's not necessary live by now. > return 0; > } > > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 3436c6bf7c0c..d300fe9415bd 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -146,7 +146,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. > + * 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]; > -- > 2.18.0