Re: [PATCH v5 3/4] lib/test_kasan.c: add workqueue test case

From: Walter Wu
Date: Thu Dec 03 2020 - 20:33:22 EST


On Thu, 2020-12-03 at 11:29 +0100, Marco Elver wrote:
> On Thu, 3 Dec 2020 at 03:27, Walter Wu <walter-zh.wu@xxxxxxxxxxxx> wrote:
> >
> > Adds a test to verify workqueue stack recording and print it in
> > KASAN report.
> >
> > The KASAN report was as follows(cleaned up slightly):
> >
> > BUG: KASAN: use-after-free in kasan_workqueue_uaf
> >
> > Freed by task 54:
> > kasan_save_stack+0x24/0x50
> > kasan_set_track+0x24/0x38
> > kasan_set_free_info+0x20/0x40
> > __kasan_slab_free+0x10c/0x170
> > kasan_slab_free+0x10/0x18
> > kfree+0x98/0x270
> > kasan_workqueue_work+0xc/0x18
> >
> > Last potentially related work creation:
> > kasan_save_stack+0x24/0x50
> > kasan_record_wq_stack+0xa8/0xb8
> > insert_work+0x48/0x288
> > __queue_work+0x3e8/0xc40
> > queue_work_on+0xf4/0x118
> > kasan_workqueue_uaf+0xfc/0x190
> >
> > Signed-off-by: Walter Wu <walter-zh.wu@xxxxxxxxxxxx>
> > Acked-by: Marco Elver <elver@xxxxxxxxxx>
> > Reviewed-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx>
> > Reviewed-by: Andrey Konovalov <andreyknvl@xxxxxxxxxx>
> > Cc: Andrey Ryabinin <aryabinin@xxxxxxxxxxxxx>
> > Cc: Alexander Potapenko <glider@xxxxxxxxxx>
> > Cc: Matthias Brugger <matthias.bgg@xxxxxxxxx>
> > ---
> >
> > v4:
> > - testcase has merge conflict, so that rebase onto the KASAN-KUNIT
> >
> > ---
> > lib/test_kasan_module.c | 29 +++++++++++++++++++++++++++++
> > 1 file changed, 29 insertions(+)
> >
> > diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
> > index 2d68db6ae67b..62a87854b120 100644
> > --- a/lib/test_kasan_module.c
> > +++ b/lib/test_kasan_module.c
> > @@ -91,6 +91,34 @@ static noinline void __init kasan_rcu_uaf(void)
> > call_rcu(&global_rcu_ptr->rcu, kasan_rcu_reclaim);
> > }
> >
> > +static noinline void __init kasan_workqueue_work(struct work_struct *work)
> > +{
> > + kfree(work);
> > +}
> > +
> > +static noinline void __init kasan_workqueue_uaf(void)
> > +{
> > + struct workqueue_struct *workqueue;
> > + struct work_struct *work;
> > +
> > + workqueue = create_workqueue("kasan_wq_test");
> > + if (!workqueue) {
> > + pr_err("Allocation failed\n");
> > + return;
> > + }
> > + work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
> > + if (!work) {
> > + pr_err("Allocation failed\n");
> > + return;
> > + }
> > +
> > + INIT_WORK(work, kasan_workqueue_work);
> > + queue_work(workqueue, work);
> > + destroy_workqueue(workqueue);
> > +
> > + pr_info("use-after-free on workqueue\n");
> > + ((volatile struct work_struct *)work)->data;
> > +}
> >
> > static int __init test_kasan_module_init(void)
> > {
> > @@ -102,6 +130,7 @@ static int __init test_kasan_module_init(void)
> >
> > copy_user_test();
> > kasan_rcu_uaf();
> > + kasan_workqueue_uaf();
>
>
> Why can't this go into the KUnit based KASAN test?

This test case has not been ported to KUnit, because KUnit's expect
failure will not check whether the work stack is exist. So it remains in
test_kasan_module, it is the same with kasan_rcu_uaf()[1].

[1]https://lkml.org/lkml/2020/8/1/45

Thanks.
Walter