* [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails
@ 2025-10-26 9:13 Miaoqian Lin
2025-10-27 10:14 ` Heiko Carstens
0 siblings, 1 reply; 4+ messages in thread
From: Miaoqian Lin @ 2025-10-26 9:13 UTC (permalink / raw)
To: Alexander Gordeev, Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
Christian Borntraeger, Sven Schnelle, linux-s390, linux-kernel,
bpf
Cc: linmq006, stable
When kvrealloc() fails, the original markers memory is leaked
because the function directly assigns the NULL to the markers pointer,
losing the reference to the original memory.
As a result, the kvfree() in pt_dump_init() ends up freeing NULL instead
of the previously allocated memory.
Fix this by using a temporary variable to store kvrealloc()'s return
value and only update the markers pointer on success.
Found via static anlaysis 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>
---
arch/s390/mm/dump_pagetables.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index 9af2aae0a515..0f2e0c93a1e0 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -291,16 +291,19 @@ static int ptdump_cmp(const void *a, const void *b)
static int add_marker(unsigned long start, unsigned long end, const char *name)
{
+ struct addr_marker *new_markers;
size_t oldsize, newsize;
oldsize = markers_cnt * sizeof(*markers);
newsize = oldsize + 2 * sizeof(*markers);
if (!oldsize)
- markers = kvmalloc(newsize, GFP_KERNEL);
+ new_markers = kvmalloc(newsize, GFP_KERNEL);
else
- markers = kvrealloc(markers, newsize, GFP_KERNEL);
- if (!markers)
+ new_markers = kvrealloc(markers, newsize, GFP_KERNEL);
+ if (!new_markers)
goto error;
+
+ markers = new_markers;
markers[markers_cnt].is_start = 1;
markers[markers_cnt].start_address = start;
markers[markers_cnt].size = end - start;
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails 2025-10-26 9:13 [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails Miaoqian Lin @ 2025-10-27 10:14 ` Heiko Carstens 2025-10-27 11:53 ` 林妙倩 0 siblings, 1 reply; 4+ messages in thread From: Heiko Carstens @ 2025-10-27 10:14 UTC (permalink / raw) To: Miaoqian Lin Cc: Alexander Gordeev, Gerald Schaefer, Vasily Gorbik, Christian Borntraeger, Sven Schnelle, linux-s390, linux-kernel, bpf, stable On Sun, Oct 26, 2025 at 05:13:51PM +0800, Miaoqian Lin wrote: > When kvrealloc() fails, the original markers memory is leaked > because the function directly assigns the NULL to the markers pointer, > losing the reference to the original memory. > > As a result, the kvfree() in pt_dump_init() ends up freeing NULL instead > of the previously allocated memory. > > Fix this by using a temporary variable to store kvrealloc()'s return > value and only update the markers pointer on success. > > Found via static anlaysis 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> > --- > arch/s390/mm/dump_pagetables.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c > index 9af2aae0a515..0f2e0c93a1e0 100644 > --- a/arch/s390/mm/dump_pagetables.c > +++ b/arch/s390/mm/dump_pagetables.c > @@ -291,16 +291,19 @@ static int ptdump_cmp(const void *a, const void *b) > > static int add_marker(unsigned long start, unsigned long end, const char *name) > { > + struct addr_marker *new_markers; > size_t oldsize, newsize; > > oldsize = markers_cnt * sizeof(*markers); > newsize = oldsize + 2 * sizeof(*markers); > if (!oldsize) > - markers = kvmalloc(newsize, GFP_KERNEL); > + new_markers = kvmalloc(newsize, GFP_KERNEL); > else > - markers = kvrealloc(markers, newsize, GFP_KERNEL); > - if (!markers) > + new_markers = kvrealloc(markers, newsize, GFP_KERNEL); > + if (!new_markers) > goto error; > + > + markers = new_markers; This is not better to the situation before. If the allocation fails, markers_cnt will be set to zero, but the old valid markers pointer will stay, which means that the next call to add_marker() will allocate a new area via kvmalloc() instead of kvrealloc(), and thus leaking the old area too. add_marker() needs to changes to return in a manner that both marker and marker_cnt correlate with each other. And I guess it is also easily possible to get rid of the two different allocation paths. Care to send a new version? ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails 2025-10-27 10:14 ` Heiko Carstens @ 2025-10-27 11:53 ` 林妙倩 2025-10-27 12:31 ` Heiko Carstens 0 siblings, 1 reply; 4+ messages in thread From: 林妙倩 @ 2025-10-27 11:53 UTC (permalink / raw) To: Heiko Carstens Cc: Alexander Gordeev, Gerald Schaefer, Vasily Gorbik, Christian Borntraeger, Sven Schnelle, linux-s390, linux-kernel, bpf, stable Hi, Heiko Thank you for the feedback. Heiko Carstens <hca@linux.ibm.com> 于2025年10月27日周一 18:15写道: > > On Sun, Oct 26, 2025 at 05:13:51PM +0800, Miaoqian Lin wrote: > > When kvrealloc() fails, the original markers memory is leaked > > because the function directly assigns the NULL to the markers pointer, > > losing the reference to the original memory. > > > > As a result, the kvfree() in pt_dump_init() ends up freeing NULL instead > > of the previously allocated memory. > > > > Fix this by using a temporary variable to store kvrealloc()'s return > > value and only update the markers pointer on success. > > > > Found via static anlaysis 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> > > --- > > arch/s390/mm/dump_pagetables.c | 9 ++++++--- > > 1 file changed, 6 insertions(+), 3 deletions(-) > > > > diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c > > index 9af2aae0a515..0f2e0c93a1e0 100644 > > --- a/arch/s390/mm/dump_pagetables.c > > +++ b/arch/s390/mm/dump_pagetables.c > > @@ -291,16 +291,19 @@ static int ptdump_cmp(const void *a, const void *b) > > > > static int add_marker(unsigned long start, unsigned long end, const char *name) > > { > > + struct addr_marker *new_markers; > > size_t oldsize, newsize; > > > > oldsize = markers_cnt * sizeof(*markers); > > newsize = oldsize + 2 * sizeof(*markers); > > if (!oldsize) > > - markers = kvmalloc(newsize, GFP_KERNEL); > > + new_markers = kvmalloc(newsize, GFP_KERNEL); > > else > > - markers = kvrealloc(markers, newsize, GFP_KERNEL); > > - if (!markers) > > + new_markers = kvrealloc(markers, newsize, GFP_KERNEL); > > + if (!new_markers) > > goto error; > > + > > + markers = new_markers; > > This is not better to the situation before. If the allocation fails, > markers_cnt will be set to zero, but the old valid markers pointer will stay, > which means that the next call to add_marker() will allocate a new area via > kvmalloc() instead of kvrealloc(), and thus leaking the old area too. > > add_marker() needs to changes to return in a manner that both marker and > marker_cnt correlate with each other. And I guess it is also easily possible > to get rid of the two different allocation paths. > > Care to send a new version? I'm not sure if I can make it right. Do you think this way can fix the leak correctly? Thanks. ```diff 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_markers; + size_t newsize; + + newsize = (markers_cnt + 2) * sizeof(*markers); + new_markers = kvrealloc(markers, newsize, GFP_KERNEL); + if (!new_markers) + return -ENOMEM; + + markers = new_markers; markers[markers_cnt].is_start = 1; markers[markers_cnt].start_address = start; markers[markers_cnt].size = end - start; @@ -312,9 +311,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; } ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails 2025-10-27 11:53 ` 林妙倩 @ 2025-10-27 12:31 ` Heiko Carstens 0 siblings, 0 replies; 4+ messages in thread From: Heiko Carstens @ 2025-10-27 12:31 UTC (permalink / raw) To: 林妙倩 Cc: Alexander Gordeev, Gerald Schaefer, Vasily Gorbik, Christian Borntraeger, Sven Schnelle, linux-s390, linux-kernel, bpf, stable On Mon, Oct 27, 2025 at 07:53:25PM +0800, 林妙倩 wrote: > > Care to send a new version? > > I'm not sure if I can make it right. > Do you think this way can fix the leak correctly? Thanks. > > ```diff > 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_markers; > + size_t newsize; > + > + newsize = (markers_cnt + 2) * sizeof(*markers); > + new_markers = kvrealloc(markers, newsize, GFP_KERNEL); > + if (!new_markers) > + return -ENOMEM; > + > + markers = new_markers; > markers[markers_cnt].is_start = 1; > markers[markers_cnt].start_address = start; > markers[markers_cnt].size = end - start; > @@ -312,9 +311,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; > } Not exactly what I had in mind, but this looks good too. Could you send a proper second version of your patch, please? Thanks! ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-10-27 12:31 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-10-26 9:13 [PATCH] s390/mm: Fix memory leak in add_marker() when kvrealloc fails Miaoqian Lin 2025-10-27 10:14 ` Heiko Carstens 2025-10-27 11:53 ` 林妙倩 2025-10-27 12:31 ` Heiko Carstens
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).