Message ID | 2815073f2be37e554f7f0fd7b1d10e9742be6ce3.1664044241.git.andreyknvl@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [mm,1/3] kasan: switch kunit tests to console tracepoints | expand |
On Sat, Sep 24, 2022 at 08:31PM +0200, andrey.konovalov@linux.dev wrote: > From: Andrey Konovalov <andreyknvl@google.com> > > Migrate the workqueue_uaf test to the KUnit framework. > > Initially, this test was intended to check that Generic KASAN prints > auxiliary stack traces for workqueues. Nevertheless, the test is enabled > for all modes to make that KASAN reports bad accesses in the tested > scenario. > > The presence of auxiliary stack traces for the Generic mode needs to be > inspected manually. > > Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Reviewed-by: Marco Elver <elver@google.com> > --- > mm/kasan/kasan_test.c | 40 +++++++++++++++++++++++++++++------- > mm/kasan/kasan_test_module.c | 30 --------------------------- > 2 files changed, 33 insertions(+), 37 deletions(-) > > diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c > index 005776325e20..71cb402c404f 100644 > --- a/mm/kasan/kasan_test.c > +++ b/mm/kasan/kasan_test.c > @@ -1134,6 +1134,14 @@ static void kmalloc_double_kzfree(struct kunit *test) > KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr)); > } > > +/* > + * The two tests below check that Generic KASAN prints auxiliary stack traces > + * for RCU callbacks and workqueues. The reports need to be inspected manually. > + * > + * These tests are still enabled for other KASAN modes to make sure that all > + * modes report bad accesses in tested scenarios. > + */ > + > static struct kasan_rcu_info { > int i; > struct rcu_head rcu; > @@ -1148,13 +1156,6 @@ static void rcu_uaf_reclaim(struct rcu_head *rp) > ((volatile struct kasan_rcu_info *)fp)->i; > } > > -/* > - * Check that Generic KASAN prints auxiliary stack traces for RCU callbacks. > - * The report needs to be inspected manually. > - * > - * This test is still enabled for other KASAN modes to make sure that all modes > - * report bad accesses in tested scenarios. > - */ > static void rcu_uaf(struct kunit *test) > { > struct kasan_rcu_info *ptr; > @@ -1170,6 +1171,30 @@ static void rcu_uaf(struct kunit *test) > rcu_barrier()); > } > > +static void workqueue_uaf_work(struct work_struct *work) > +{ > + kfree(work); > +} > + > +static void workqueue_uaf(struct kunit *test) > +{ > + struct workqueue_struct *workqueue; > + struct work_struct *work; > + > + workqueue = create_workqueue("kasan_workqueue_test"); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, workqueue); > + > + work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); > + > + INIT_WORK(work, workqueue_uaf_work); > + queue_work(workqueue, work); > + destroy_workqueue(workqueue); > + > + KUNIT_EXPECT_KASAN_FAIL(test, > + ((volatile struct work_struct *)work)->data); > +} > + > static void vmalloc_helpers_tags(struct kunit *test) > { > void *ptr; > @@ -1502,6 +1527,7 @@ static struct kunit_case kasan_kunit_test_cases[] = { > KUNIT_CASE(kasan_bitops_tags), > KUNIT_CASE(kmalloc_double_kzfree), > KUNIT_CASE(rcu_uaf), > + KUNIT_CASE(workqueue_uaf), > KUNIT_CASE(vmalloc_helpers_tags), > KUNIT_CASE(vmalloc_oob), > KUNIT_CASE(vmap_tags), > diff --git a/mm/kasan/kasan_test_module.c b/mm/kasan/kasan_test_module.c > index 4688cbcd722d..7be7bed456ef 100644 > --- a/mm/kasan/kasan_test_module.c > +++ b/mm/kasan/kasan_test_module.c > @@ -62,35 +62,6 @@ static noinline void __init copy_user_test(void) > kfree(kmem); > } > > -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) > { > /* > @@ -101,7 +72,6 @@ static int __init test_kasan_module_init(void) > bool multishot = kasan_save_enable_multi_shot(); > > copy_user_test(); > - kasan_workqueue_uaf(); > > kasan_restore_multi_shot(multishot); > return -EAGAIN; > -- > 2.25.1
diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c index 005776325e20..71cb402c404f 100644 --- a/mm/kasan/kasan_test.c +++ b/mm/kasan/kasan_test.c @@ -1134,6 +1134,14 @@ static void kmalloc_double_kzfree(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr)); } +/* + * The two tests below check that Generic KASAN prints auxiliary stack traces + * for RCU callbacks and workqueues. The reports need to be inspected manually. + * + * These tests are still enabled for other KASAN modes to make sure that all + * modes report bad accesses in tested scenarios. + */ + static struct kasan_rcu_info { int i; struct rcu_head rcu; @@ -1148,13 +1156,6 @@ static void rcu_uaf_reclaim(struct rcu_head *rp) ((volatile struct kasan_rcu_info *)fp)->i; } -/* - * Check that Generic KASAN prints auxiliary stack traces for RCU callbacks. - * The report needs to be inspected manually. - * - * This test is still enabled for other KASAN modes to make sure that all modes - * report bad accesses in tested scenarios. - */ static void rcu_uaf(struct kunit *test) { struct kasan_rcu_info *ptr; @@ -1170,6 +1171,30 @@ static void rcu_uaf(struct kunit *test) rcu_barrier()); } +static void workqueue_uaf_work(struct work_struct *work) +{ + kfree(work); +} + +static void workqueue_uaf(struct kunit *test) +{ + struct workqueue_struct *workqueue; + struct work_struct *work; + + workqueue = create_workqueue("kasan_workqueue_test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, workqueue); + + work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); + + INIT_WORK(work, workqueue_uaf_work); + queue_work(workqueue, work); + destroy_workqueue(workqueue); + + KUNIT_EXPECT_KASAN_FAIL(test, + ((volatile struct work_struct *)work)->data); +} + static void vmalloc_helpers_tags(struct kunit *test) { void *ptr; @@ -1502,6 +1527,7 @@ static struct kunit_case kasan_kunit_test_cases[] = { KUNIT_CASE(kasan_bitops_tags), KUNIT_CASE(kmalloc_double_kzfree), KUNIT_CASE(rcu_uaf), + KUNIT_CASE(workqueue_uaf), KUNIT_CASE(vmalloc_helpers_tags), KUNIT_CASE(vmalloc_oob), KUNIT_CASE(vmap_tags), diff --git a/mm/kasan/kasan_test_module.c b/mm/kasan/kasan_test_module.c index 4688cbcd722d..7be7bed456ef 100644 --- a/mm/kasan/kasan_test_module.c +++ b/mm/kasan/kasan_test_module.c @@ -62,35 +62,6 @@ static noinline void __init copy_user_test(void) kfree(kmem); } -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) { /* @@ -101,7 +72,6 @@ static int __init test_kasan_module_init(void) bool multishot = kasan_save_enable_multi_shot(); copy_user_test(); - kasan_workqueue_uaf(); kasan_restore_multi_shot(multishot); return -EAGAIN;