Commit 6ee9b3d8 authored by Yeoreum Yun's avatar Yeoreum Yun Committed by Andrew Morton
Browse files

kasan: remove kasan_find_vm_area() to prevent possible deadlock

find_vm_area() couldn't be called in atomic_context.  If find_vm_area() is
called to reports vm area information, kasan can trigger deadlock like:

CPU0                                CPU1
vmalloc();
 alloc_vmap_area();
  spin_lock(&vn->busy.lock)
                                    spin_lock_bh(&some_lock);
   <interrupt occurs>
   <in softirq>
   spin_lock(&some_lock);
                                    <access invalid address>
                                    kasan_report();
                                     print_report();
                                      print_address_description();
                                       kasan_find_vm_area();
                                        find_vm_area();
                                         spin_lock(&vn->busy.lock) // deadlock!

To prevent possible deadlock while kasan reports, remove kasan_find_vm_area().

Link: https://lkml.kernel.org/r/20250703181018.580833-1-yeoreum.yun@arm.com


Fixes: c056a364 ("kasan: print virtual mapping info in reports")
Signed-off-by: default avatarYeoreum Yun <yeoreum.yun@arm.com>
Reported-by: default avatarYunseong Kim <ysk@kzalloc.com>
Reviewed-by: default avatarAndrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent e6d3e653
Loading
Loading
Loading
Loading
+2 −43
Original line number Diff line number Diff line
@@ -370,36 +370,6 @@ static inline bool init_task_stack_addr(const void *addr)
			sizeof(init_thread_union.stack));
}

/*
 * This function is invoked with report_lock (a raw_spinlock) held. A
 * PREEMPT_RT kernel cannot call find_vm_area() as it will acquire a sleeping
 * rt_spinlock.
 *
 * For !RT kernel, the PROVE_RAW_LOCK_NESTING config option will print a
 * lockdep warning for this raw_spinlock -> spinlock dependency. This config
 * option is enabled by default to ensure better test coverage to expose this
 * kind of RT kernel problem. This lockdep splat, however, can be suppressed
 * by using DEFINE_WAIT_OVERRIDE_MAP() if it serves a useful purpose and the
 * invalid PREEMPT_RT case has been taken care of.
 */
static inline struct vm_struct *kasan_find_vm_area(void *addr)
{
	static DEFINE_WAIT_OVERRIDE_MAP(vmalloc_map, LD_WAIT_SLEEP);
	struct vm_struct *va;

	if (IS_ENABLED(CONFIG_PREEMPT_RT))
		return NULL;

	/*
	 * Suppress lockdep warning and fetch vmalloc area of the
	 * offending address.
	 */
	lock_map_acquire_try(&vmalloc_map);
	va = find_vm_area(addr);
	lock_map_release(&vmalloc_map);
	return va;
}

static void print_address_description(void *addr, u8 tag,
				      struct kasan_report_info *info)
{
@@ -429,19 +399,8 @@ static void print_address_description(void *addr, u8 tag,
	}

	if (is_vmalloc_addr(addr)) {
		struct vm_struct *va = kasan_find_vm_area(addr);

		if (va) {
			pr_err("The buggy address belongs to the virtual mapping at\n"
			       " [%px, %px) created by:\n"
			       " %pS\n",
			       va->addr, va->addr + va->size, va->caller);
			pr_err("\n");

			page = vmalloc_to_page(addr);
		} else {
		pr_err("The buggy address %px belongs to a vmalloc virtual mapping\n", addr);
		}
		page = vmalloc_to_page(addr);
	}

	if (page) {