Skip to content

Commit 7ecd2e4

Browse files
prati0100akpm00
authored andcommitted
kho: fix unpreservation of higher-order vmalloc preservations
kho_vmalloc_unpreserve_chunk() calls __kho_unpreserve() with end_pfn as pfn + 1. This happens to work for 0-order pages, but leaks higher order pages. For example, say order 2 pages back the allocation. During preservation, they get preserved in the order 2 bitmaps, but kho_vmalloc_unpreserve_chunk() would try to unpreserve them from the order 0 bitmaps, which should not have these bits set anyway, leaving the order 2 bitmaps untouched. This results in the pages being carried over to the next kernel. Nothing will free those pages in the next boot, leaking them. Fix this by taking the order into account when calculating the end PFN for __kho_unpreserve(). Link: https://lkml.kernel.org/r/20251103180235.71409-2-pratyush@kernel.org Fixes: a667300 ("kho: add support for preserving vmalloc allocations") Signed-off-by: Pratyush Yadav <pratyush@kernel.org> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Alexander Graf <graf@amazon.com> Cc: Baoquan He <bhe@redhat.com> Cc: Pasha Tatashin <pasha.tatashin@soleen.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 0b07092 commit 7ecd2e4

1 file changed

Lines changed: 4 additions & 3 deletions

File tree

kernel/kexec_handover.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,8 @@ static struct kho_vmalloc_chunk *new_vmalloc_chunk(struct kho_vmalloc_chunk *cur
882882
return NULL;
883883
}
884884

885-
static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk)
885+
static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk,
886+
unsigned short order)
886887
{
887888
struct kho_mem_track *track = &kho_out.ser.track;
888889
unsigned long pfn = PHYS_PFN(virt_to_phys(chunk));
@@ -891,7 +892,7 @@ static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk)
891892

892893
for (int i = 0; i < ARRAY_SIZE(chunk->phys) && chunk->phys[i]; i++) {
893894
pfn = PHYS_PFN(chunk->phys[i]);
894-
__kho_unpreserve(track, pfn, pfn + 1);
895+
__kho_unpreserve(track, pfn, pfn + (1 << order));
895896
}
896897
}
897898

@@ -902,7 +903,7 @@ static void kho_vmalloc_free_chunks(struct kho_vmalloc *kho_vmalloc)
902903
while (chunk) {
903904
struct kho_vmalloc_chunk *tmp = chunk;
904905

905-
kho_vmalloc_unpreserve_chunk(chunk);
906+
kho_vmalloc_unpreserve_chunk(chunk, kho_vmalloc->order);
906907

907908
chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
908909
free_page((unsigned long)tmp);

0 commit comments

Comments
 (0)