mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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) <willy@infradead.org> Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20220110231530.665970-3-willy@infradead.org
This commit is contained in:
		
							parent
							
								
									4e140f59d2
								
							
						
					
					
						commit
						0aef499f31
					
				
					 1 changed files with 16 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -17,6 +17,7 @@
 | 
			
		|||
#include <linux/sched/task.h>
 | 
			
		||||
#include <linux/sched/task_stack.h>
 | 
			
		||||
#include <linux/thread_info.h>
 | 
			
		||||
#include <linux/vmalloc.h>
 | 
			
		||||
#include <linux/atomic.h>
 | 
			
		||||
#include <linux/jump_label.h>
 | 
			
		||||
#include <asm/sections.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -238,6 +239,21 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_vmalloc_addr(ptr)) {
 | 
			
		||||
		struct vm_struct *area = find_vm_area(ptr);
 | 
			
		||||
		unsigned long offset;
 | 
			
		||||
 | 
			
		||||
		if (!area) {
 | 
			
		||||
			usercopy_abort("vmalloc", "no area", to_user, 0, n);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offset = ptr - area->addr;
 | 
			
		||||
		if (offset + n > get_vm_area_size(area))
 | 
			
		||||
			usercopy_abort("vmalloc", NULL, to_user, offset, n);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	folio = virt_to_folio(ptr);
 | 
			
		||||
 | 
			
		||||
	if (folio_test_slab(folio)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue