Skip to contentSkip to conversation

mm/vmalloc: fix vmalloc_dump_obj VA lookup

PATCH Superseded Ye Liu 2 participants 5 messages Sep 16 – Sep 17

Subsystems (2)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Ye Liu

author
#0 lore raw

cover mm/vmalloc: fix vmalloc_dump_obj VA lookup

vmalloc_dump_obj() has two bugs that cause it to miss vmalloc allocations, plus a minor optimization opportunity:

1. PAGE_ALIGN() rounds up, pushing last-page addresses to va_end and outside the VA lookup range.

2. The function searches only one vmap node, but allocations larger than 64 KiB may span multiple vmap zones whose VA is stored in a different node's rb-tree.

Patch 1 fixes the alignment, patch 2 fixes the cross-zone search, patch 3 adds an early is_vmalloc_addr() check to skip non-vmalloc addresses without traversing all nodes.

---
Ye Liu (3):
mm/vmalloc: fix vmalloc_dump_obj address alignment for last-page lookups mm/vmalloc: fix vmalloc_dump_obj cross-zone VA lookup mm/vmalloc: skip vmalloc_dump_obj for non-vmalloc addresses

 mm/vmalloc.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

---
base-commit: e6e35979777d646fe3c7c94dca7dd32fb25d45f4
change-id: 20260916-vmalloc_dump_obj-d80908447369

Best regards,

Signature · 1 line
Ye Liu <[email protected]>
author
#1 lore raw

PATCH 1/3 mm/vmalloc: fix vmalloc_dump_obj address alignment for last-page lookups

From: Ye Liu <[email protected]>

vmalloc_dump_obj() uses PAGE_ALIGN() to normalize the input address before looking it up in the per-node busy tree. PAGE_ALIGN() rounds up, which can push an address in the last page of a vmalloc allocation to va_end -- outside the [va_start, va_end) range that __find_vmap_area() searches. This causes the lookup to miss the VA and return false, degrading diagnostic output in OOM dumps and KASAN reports to the less informative "vmalloc memory" fallback.

The upward alignment can also change the addr_to_node() mapping when the page boundary crosses a vmap zone boundary, causing the search to hit the wrong node entirely.

Use PAGE_ALIGN_DOWN() instead, which rounds down to the page containing the address. This keeps the address within the VA range and preserves the correct node mapping.

---
 mm/vmalloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmalloc.c +1 -1
index 859e6d2d57a3..df42d8a6f058 100644
@@ -5277,7 +5277,7 @@ bool vmalloc_dump_obj(void *object)
 	unsigned long addr;
 	unsigned long nr_pages;
 
-	addr = PAGE_ALIGN((unsigned long) object);
+	addr = PAGE_ALIGN_DOWN((unsigned long) object);
 	vn = addr_to_node(addr);
 
 	if (!spin_trylock(&vn->busy.lock))
Signature · 1 line
2.25.1
author
#2 lore raw

PATCH 2/3 mm/vmalloc: fix vmalloc_dump_obj cross-zone VA lookup

In reply to Ye Liu

From: Ye Liu <[email protected]>

vmalloc_dump_obj() searches only one vmap node (addr_to_node(addr)), but a vmalloc allocation may span multiple vmap zones. The VA is stored in only one node's rb-tree (addr_to_node(va_start)), so an object pointer in a different zone than va_start maps to a different node and the search misses. This affects any allocation larger than vmap_zone_size (64 KiB) on multi-CPU systems.

Iterate all vmap nodes using for_each_vmap_node, like find_vmap_area() does, but with spin_trylock instead of spin_lock as this function can be called from atomic dump contexts (OOM, KASAN, RCU).

---
 mm/vmalloc.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
mm/vmalloc.c +18 -6
index df42d8a6f058..30c610f678dc 100644
@@ -5278,17 +5278,29 @@ bool vmalloc_dump_obj(void *object)
 	unsigned long nr_pages;
 
 	addr = PAGE_ALIGN_DOWN((unsigned long) object);
-	vn = addr_to_node(addr);
 
-	if (!spin_trylock(&vn->busy.lock))
-		return false;
+	/*
+	 * A vmalloc allocation may span multiple vmap zones, so the
+	 * node whose rb-tree holds the VA may differ from the node
+	 * the address maps to.  Search all nodes.  Use trylock as
+	 * this function can be called from atomic dump contexts.
+	 */
+	va = NULL;
+	for_each_vmap_node(vn) {
+		if (!spin_trylock(&vn->busy.lock))
+			continue;
+
+		va = __find_vmap_area(addr, &vn->busy.root);
+		if (va && va->vm)
+			break;
 
-	va = __find_vmap_area(addr, &vn->busy.root);
-	if (!va || !va->vm) {
 		spin_unlock(&vn->busy.lock);
-		return false;
+		va = NULL;
 	}
 
+	if (!va)
+		return false;
+
 	vm = va->vm;
 	addr = (unsigned long) vm->addr;
 	caller = vm->caller;
Signature · 1 line
2.25.1
author
#3 lore raw

PATCH 3/3 mm/vmalloc: skip vmalloc_dump_obj for non-vmalloc addresses

In reply to Ye Liu

From: Ye Liu <[email protected]>

vmalloc_dump_obj() unconditionally searches all vmap nodes even when called with a non-vmalloc address (e.g. a slab or stack pointer from mem_dump_obj()). Add an is_vmalloc_addr() check at the entry to avoid the unnecessary per-node trylock and rb-tree traversal.

The KASAN caller already gates on is_vmalloc_addr(), but mem_dump_obj() calls vmalloc_dump_obj() before the fallback type check, so the guard in the callee covers both paths without requiring caller changes.

---
 mm/vmalloc.c | 3 +++
 1 file changed, 3 insertions(+)
mm/vmalloc.c +3 -0
index 30c610f678dc..b3e706fde202 100644
@@ -5277,6 +5277,9 @@ bool vmalloc_dump_obj(void *object)
 	unsigned long addr;
 	unsigned long nr_pages;
 
+	if (!is_vmalloc_addr(object))
+		return false;
+
 	addr = PAGE_ALIGN_DOWN((unsigned long) object);
 
 	/*
Signature · 1 line
2.25.1
maintainer
#4 lore raw
In reply to Ye Liu
Quoted 6 lines · On Wed, 16 Sep 2026 16:25:27 +0800 Ye Liu <[email protected]> wrote:

vmalloc_dump_obj() has two bugs that cause it to miss vmalloc allocations, plus a minor optimization opportunity:

1. PAGE_ALIGN() rounds up, pushing last-page addresses to va_end and outside the VA lookup range.

Quoted 8 lines

2. The function searches only one vmap node, but allocations larger than 64 KiB may span multiple vmap zones whose VA is stored in a different node's rb-tree.

Patch 1 fixes the alignment, patch 2 fixes the cross-zone search, patch 3 adds an early is_vmalloc_addr() check to skip non-vmalloc addresses without traversing all nodes.

Thanks. Sashiko asked a thing:

	https://sashiko.dev/#/patchset/[email protected]