Skip to content

Commit 993d0b2

Browse files
Matthew Wilcox (Oracle)kees
authored andcommitted
usercopy: Handle vm_map_ram() areas
vmalloc does not allocate a vm_struct for vm_map_ram() areas. That causes us to deny usercopies from those areas. This affects XFS which uses vm_map_ram() for its directories. Fix this by calling find_vmap_area() instead of find_vm_area(). Fixes: 0aef499 ("mm/usercopy: Detect vmalloc overruns") Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Reviewed-by: Uladzislau Rezki (Sony) <[email protected]> Tested-by: Zorro Lang <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 57cd6d1 commit 993d0b2

File tree

3 files changed

+6
-7
lines changed

3 files changed

+6
-7
lines changed

include/linux/vmalloc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ extern struct vm_struct *__get_vm_area_caller(unsigned long size,
215215
void free_vm_area(struct vm_struct *area);
216216
extern struct vm_struct *remove_vm_area(const void *addr);
217217
extern struct vm_struct *find_vm_area(const void *addr);
218+
struct vmap_area *find_vmap_area(unsigned long addr);
218219

219220
static inline bool is_vm_area_hugepages(const void *addr)
220221
{

mm/usercopy.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,14 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
173173
}
174174

175175
if (is_vmalloc_addr(ptr)) {
176-
struct vm_struct *area = find_vm_area(ptr);
176+
struct vmap_area *area = find_vmap_area((unsigned long)ptr);
177177
unsigned long offset;
178178

179-
if (!area) {
179+
if (!area)
180180
usercopy_abort("vmalloc", "no area", to_user, 0, n);
181-
return;
182-
}
183181

184-
offset = ptr - area->addr;
185-
if (offset + n > get_vm_area_size(area))
182+
offset = (unsigned long)ptr - area->va_start;
183+
if ((unsigned long)ptr + n > area->va_end)
186184
usercopy_abort("vmalloc", NULL, to_user, offset, n);
187185
return;
188186
}

mm/vmalloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,7 @@ static void free_unmap_vmap_area(struct vmap_area *va)
17981798
free_vmap_area_noflush(va);
17991799
}
18001800

1801-
static struct vmap_area *find_vmap_area(unsigned long addr)
1801+
struct vmap_area *find_vmap_area(unsigned long addr)
18021802
{
18031803
struct vmap_area *va;
18041804

0 commit comments

Comments
 (0)