Skip to content

Commit 7ca3027

Browse files
daxtenstorvalds
authored andcommitted
mm/vmalloc: unbreak kasan vmalloc support
In commit 121e6f3 ("mm/vmalloc: hugepage vmalloc mappings"), __vmalloc_node_range was changed such that __get_vm_area_node was no longer called with the requested/real size of the vmalloc allocation, but rather with a rounded-up size. This means that __get_vm_area_node called kasan_unpoision_vmalloc() with a rounded up size rather than the real size. This led to it allowing access to too much memory and so missing vmalloc OOBs and failing the kasan kunit tests. Pass the real size and the desired shift into __get_vm_area_node. This allows it to round up the size for the underlying allocators while still unpoisioning the correct quantity of shadow memory. Adjust the other call-sites to pass in PAGE_SHIFT for the shift value. Link: https://lkml.kernel.org/r/[email protected] Link: https://bugzilla.kernel.org/show_bug.cgi?id=213335 Fixes: 121e6f3 ("mm/vmalloc: hugepage vmalloc mappings") Signed-off-by: Daniel Axtens <[email protected]> Tested-by: David Gow <[email protected]> Reviewed-by: Nicholas Piggin <[email protected]> Reviewed-by: Uladzislau Rezki (Sony) <[email protected]> Tested-by: Andrey Konovalov <[email protected]> Acked-by: Andrey Konovalov <[email protected]> Cc: Dmitry Vyukov <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 185cca2 commit 7ca3027

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

mm/vmalloc.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,15 +2344,16 @@ static void clear_vm_uninitialized_flag(struct vm_struct *vm)
23442344
}
23452345

23462346
static struct vm_struct *__get_vm_area_node(unsigned long size,
2347-
unsigned long align, unsigned long flags, unsigned long start,
2348-
unsigned long end, int node, gfp_t gfp_mask, const void *caller)
2347+
unsigned long align, unsigned long shift, unsigned long flags,
2348+
unsigned long start, unsigned long end, int node,
2349+
gfp_t gfp_mask, const void *caller)
23492350
{
23502351
struct vmap_area *va;
23512352
struct vm_struct *area;
23522353
unsigned long requested_size = size;
23532354

23542355
BUG_ON(in_interrupt());
2355-
size = PAGE_ALIGN(size);
2356+
size = ALIGN(size, 1ul << shift);
23562357
if (unlikely(!size))
23572358
return NULL;
23582359

@@ -2384,8 +2385,8 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
23842385
unsigned long start, unsigned long end,
23852386
const void *caller)
23862387
{
2387-
return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE,
2388-
GFP_KERNEL, caller);
2388+
return __get_vm_area_node(size, 1, PAGE_SHIFT, flags, start, end,
2389+
NUMA_NO_NODE, GFP_KERNEL, caller);
23892390
}
23902391

23912392
/**
@@ -2401,15 +2402,17 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
24012402
*/
24022403
struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
24032404
{
2404-
return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
2405+
return __get_vm_area_node(size, 1, PAGE_SHIFT, flags,
2406+
VMALLOC_START, VMALLOC_END,
24052407
NUMA_NO_NODE, GFP_KERNEL,
24062408
__builtin_return_address(0));
24072409
}
24082410

24092411
struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
24102412
const void *caller)
24112413
{
2412-
return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
2414+
return __get_vm_area_node(size, 1, PAGE_SHIFT, flags,
2415+
VMALLOC_START, VMALLOC_END,
24132416
NUMA_NO_NODE, GFP_KERNEL, caller);
24142417
}
24152418

@@ -2902,9 +2905,9 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
29022905
}
29032906

29042907
again:
2905-
size = PAGE_ALIGN(size);
2906-
area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
2907-
vm_flags, start, end, node, gfp_mask, caller);
2908+
area = __get_vm_area_node(real_size, align, shift, VM_ALLOC |
2909+
VM_UNINITIALIZED | vm_flags, start, end, node,
2910+
gfp_mask, caller);
29082911
if (!area) {
29092912
warn_alloc(gfp_mask, NULL,
29102913
"vmalloc size %lu allocation failure: "
@@ -2923,6 +2926,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
29232926
*/
29242927
clear_vm_uninitialized_flag(area);
29252928

2929+
size = PAGE_ALIGN(size);
29262930
kmemleak_vmalloc(area, size, gfp_mask);
29272931

29282932
return addr;

0 commit comments

Comments
 (0)