mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-01 00:58:39 +02:00 
			
		
		
		
	mm: keep a guard page below a grow-down stack segment
This is a rather minimally invasive patch to solve the problem of the user stack growing into a memory mapped area below it. Whenever we fill the first page of the stack segment, expand the segment down by one page. Now, admittedly some odd application might _want_ the stack to grow down into the preceding memory mapping, and so we may at some point need to make this a process tunable (some people might also want to have more than a single page of guarding), but let's try the minimal approach first. Tested with trivial application that maps a single page just below the stack, and then starts recursing. Without this, we will get a SIGSEGV _after_ the stack has smashed the mapping. With this patch, we'll get a nice SIGBUS just as the stack touches the page just above the mapping. Requested-by: Keith Packard <keithp@keithp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									2069601b3f
								
							
						
					
					
						commit
						320b2b8de1
					
				
					 1 changed files with 23 additions and 0 deletions
				
			
		
							
								
								
									
										23
									
								
								mm/memory.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								mm/memory.c
									
									
									
									
									
								
							|  | @ -2759,6 +2759,26 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This is like a special single-page "expand_downwards()", | ||||
|  * except we must first make sure that 'address-PAGE_SIZE' | ||||
|  * doesn't hit another vma. | ||||
|  * | ||||
|  * The "find_vma()" will do the right thing even if we wrap | ||||
|  */ | ||||
| static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) | ||||
| { | ||||
| 	address &= PAGE_MASK; | ||||
| 	if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { | ||||
| 		address -= PAGE_SIZE; | ||||
| 		if (find_vma(vma->vm_mm, address) != vma) | ||||
| 			return -ENOMEM; | ||||
| 
 | ||||
| 		expand_stack(vma, address); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * We enter with non-exclusive mmap_sem (to exclude vma changes, | ||||
|  * but allow concurrent faults), and pte mapped but not yet locked. | ||||
|  | @ -2772,6 +2792,9 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 	spinlock_t *ptl; | ||||
| 	pte_t entry; | ||||
| 
 | ||||
| 	if (check_stack_guard_page(vma, address) < 0) | ||||
| 		return VM_FAULT_SIGBUS; | ||||
| 
 | ||||
| 	if (!(flags & FAULT_FLAG_WRITE)) { | ||||
| 		entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), | ||||
| 						vma->vm_page_prot)); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds