Skip to content

Commit 0aef499

Browse files
Matthew Wilcox (Oracle)kees
authored andcommitted
mm/usercopy: Detect vmalloc overruns
If you have a vmalloc() allocation, or an address from calling vmap(), you cannot overrun the vm_area which describes it, regardless of the size of the underlying allocation. This probably doesn't do much for security because vmalloc comes with guard pages these days, but it prevents usercopy aborts when copying to a vmap() of smaller pages. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Acked-by: Kees Cook <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4e140f5 commit 0aef499

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

mm/usercopy.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/sched/task.h>
1818
#include <linux/sched/task_stack.h>
1919
#include <linux/thread_info.h>
20+
#include <linux/vmalloc.h>
2021
#include <linux/atomic.h>
2122
#include <linux/jump_label.h>
2223
#include <asm/sections.h>
@@ -238,6 +239,21 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
238239
return;
239240
}
240241

242+
if (is_vmalloc_addr(ptr)) {
243+
struct vm_struct *area = find_vm_area(ptr);
244+
unsigned long offset;
245+
246+
if (!area) {
247+
usercopy_abort("vmalloc", "no area", to_user, 0, n);
248+
return;
249+
}
250+
251+
offset = ptr - area->addr;
252+
if (offset + n > get_vm_area_size(area))
253+
usercopy_abort("vmalloc", NULL, to_user, offset, n);
254+
return;
255+
}
256+
241257
folio = virt_to_folio(ptr);
242258

243259
if (folio_test_slab(folio)) {

0 commit comments

Comments
 (0)