]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/mm: Fix memory leak in add_marker() when kvrealloc() fails
authorMiaoqian Lin <linmq006@gmail.com>
Mon, 27 Oct 2025 15:08:38 +0000 (23:08 +0800)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 29 Oct 2025 13:17:50 +0000 (14:17 +0100)
The function has a memory leak when kvrealloc() fails.
The function directly assigns NULL to the markers pointer, losing the
reference to the previously allocated memory. This causes kvfree() in
pt_dump_init() to free NULL instead of the leaked memory.

Fix by:
1. Using kvrealloc() uniformly for all allocations
2. Using a temporary variable to preserve the original pointer until
   allocation succeeds
3. Removing the error path that sets markers_cnt=0 to keep
   consistency between markers and markers_cnt

Found via static analysis and this is similar to commit 42378a9ca553
("bpf, verifier: Fix memory leak in array reallocation for stack state")

Fixes: d0e7915d2ad3 ("s390/mm/ptdump: Generate address marker array dynamically")
Cc: stable@vger.kernel.org
Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/mm/dump_pagetables.c

index 9af2aae0a5152a9d92e116df8b8bd910cf5ee528..528d7c70979f7d6ff6a0d356684edd1d351124be 100644 (file)
@@ -291,16 +291,14 @@ static int ptdump_cmp(const void *a, const void *b)
 
 static int add_marker(unsigned long start, unsigned long end, const char *name)
 {
-       size_t oldsize, newsize;
-
-       oldsize = markers_cnt * sizeof(*markers);
-       newsize = oldsize + 2 * sizeof(*markers);
-       if (!oldsize)
-               markers = kvmalloc(newsize, GFP_KERNEL);
-       else
-               markers = kvrealloc(markers, newsize, GFP_KERNEL);
-       if (!markers)
-               goto error;
+       struct addr_marker *new;
+       size_t newsize;
+
+       newsize = (markers_cnt + 2) * sizeof(*markers);
+       new = kvrealloc(markers, newsize, GFP_KERNEL);
+       if (!new)
+               return -ENOMEM;
+       markers = new;
        markers[markers_cnt].is_start = 1;
        markers[markers_cnt].start_address = start;
        markers[markers_cnt].size = end - start;
@@ -312,9 +310,6 @@ static int add_marker(unsigned long start, unsigned long end, const char *name)
        markers[markers_cnt].name = name;
        markers_cnt++;
        return 0;
-error:
-       markers_cnt = 0;
-       return -ENOMEM;
 }
 
 static int pt_dump_init(void)