[PATCH 3/3] tools/mm: keep the allocator scan inside the record
From: 2-D Godoy
Date: Wed Nov 04 2026 - 13:55:46 EST
get_allocator() looks for the frame above __vmalloc_node_range by walking
back to the second newline before it, without checking where the buffer
starts. When the vmalloc frame is the first stack entry of the record the
walk leaves the buffer and reads before it:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1, 1 byte to the left of a 131072-byte region
#0 get_allocator tools/mm/page_owner_sort.c:501
#1 add_list tools/mm/page_owner_sort.c:606
Remember the beginning of the line and stop at the start of the buffer.
Signed-off-by: Henrique Godoy <henrique.godoy@xxxxxxxxxxxx>
---
tools/mm/page_owner_sort.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/tools/mm/page_owner_sort.c b/tools/mm/page_owner_sort.c
index e56375f..f978988 100644
--- a/tools/mm/page_owner_sort.c
+++ b/tools/mm/page_owner_sort.c
@@ -483,6 +483,18 @@ static int get_arg_type(const char *arg)
}
}
+/*
+ * Return the beginning of the line holding @pos, never going back past the
+ * start of the buffer.
+ */
+static char *line_start(const char *buf, char *pos)
+{
+ while (pos > buf && pos[-1] != '\n')
+ pos--;
+
+ return pos;
+}
+
static int get_allocator(const char *buf, const char *migrate_info)
{
char *tmp, *first_line, *second_line;
@@ -495,13 +507,10 @@ static int get_allocator(const char *buf, const
char *migrate_info)
tmp = strstr(buf, "__vmalloc_node_range");
if (tmp) {
second_line = tmp;
- while (*tmp != '\n')
- tmp--;
- tmp--;
- while (*tmp != '\n')
- tmp--;
- first_line = ++tmp;
- tmp = strstr(tmp, "alloc_pages");
+ first_line = line_start(buf, tmp);
+ if (first_line > buf)
+ first_line = line_start(buf, first_line - 1);
+ tmp = strstr(first_line, "alloc_pages");
if (tmp && first_line <= tmp && tmp < second_line)
allocator |= ALLOCATOR_VMALLOC;
}
--
2.39.5