KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr));
 }
 
+static struct kasan_rcu_info {
+       int i;
+       struct rcu_head rcu;
+} *global_rcu_ptr;
+
+static void rcu_uaf_reclaim(struct rcu_head *rp)
+{
+       struct kasan_rcu_info *fp =
+               container_of(rp, struct kasan_rcu_info, rcu);
+
+       kfree(fp);
+       ((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;
+
+       ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
+
+       global_rcu_ptr = rcu_dereference_protected(
+                               (struct kasan_rcu_info __rcu *)ptr, NULL);
+
+       KUNIT_EXPECT_KASAN_FAIL(test,
+               call_rcu(&global_rcu_ptr->rcu, rcu_uaf_reclaim);
+               rcu_barrier());
+}
+
 static void vmalloc_helpers_tags(struct kunit *test)
 {
        void *ptr;
        KUNIT_CASE(kasan_bitops_generic),
        KUNIT_CASE(kasan_bitops_tags),
        KUNIT_CASE(kmalloc_double_kzfree),
+       KUNIT_CASE(rcu_uaf),
        KUNIT_CASE(vmalloc_helpers_tags),
        KUNIT_CASE(vmalloc_oob),
        KUNIT_CASE(vmap_tags),
 
        kfree(kmem);
 }
 
-static struct kasan_rcu_info {
-       int i;
-       struct rcu_head rcu;
-} *global_rcu_ptr;
-
-static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
-{
-       struct kasan_rcu_info *fp = container_of(rp,
-                                               struct kasan_rcu_info, rcu);
-
-       kfree(fp);
-       ((volatile struct kasan_rcu_info *)fp)->i;
-}
-
-static noinline void __init kasan_rcu_uaf(void)
-{
-       struct kasan_rcu_info *ptr;
-
-       pr_info("use-after-free in kasan_rcu_reclaim\n");
-       ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
-       if (!ptr) {
-               pr_err("Allocation failed\n");
-               return;
-       }
-
-       global_rcu_ptr = rcu_dereference_protected(ptr, NULL);
-       call_rcu(&global_rcu_ptr->rcu, kasan_rcu_reclaim);
-}
-
 static noinline void __init kasan_workqueue_work(struct work_struct *work)
 {
        kfree(work);
        bool multishot = kasan_save_enable_multi_shot();
 
        copy_user_test();
-       kasan_rcu_uaf();
        kasan_workqueue_uaf();
 
        kasan_restore_multi_shot(multishot);