mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	[PATCH] RLIMIT_AS checking fix
Address bug #4508: there's potential for wraparound in the various places where we perform RLIMIT_AS checking. (I'm a bit worried about acct_stack_growth(). Are we sure that vma->vm_mm is always equal to current->mm? If not, then we're comparing some other process's total_vm with the calling process's rlimits). Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
							parent
							
								
									f021e92101
								
							
						
					
					
						commit
						119f657c72
					
				
					 3 changed files with 23 additions and 8 deletions
				
			
		| 
						 | 
					@ -726,6 +726,7 @@ extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
 | 
				
			||||||
extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
 | 
					extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
 | 
				
			||||||
	unsigned long addr, unsigned long len, pgoff_t pgoff);
 | 
						unsigned long addr, unsigned long len, pgoff_t pgoff);
 | 
				
			||||||
extern void exit_mmap(struct mm_struct *);
 | 
					extern void exit_mmap(struct mm_struct *);
 | 
				
			||||||
 | 
					extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 | 
					extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										24
									
								
								mm/mmap.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								mm/mmap.c
									
									
									
									
									
								
							| 
						 | 
					@ -1009,8 +1009,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check against address space limit. */
 | 
						/* Check against address space limit. */
 | 
				
			||||||
	if ((mm->total_vm << PAGE_SHIFT) + len
 | 
						if (!may_expand_vm(mm, len >> PAGE_SHIFT))
 | 
				
			||||||
	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (accountable && (!(flags & MAP_NORESERVE) ||
 | 
						if (accountable && (!(flags & MAP_NORESERVE) ||
 | 
				
			||||||
| 
						 | 
					@ -1421,7 +1420,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
 | 
				
			||||||
	struct rlimit *rlim = current->signal->rlim;
 | 
						struct rlimit *rlim = current->signal->rlim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* address space limit tests */
 | 
						/* address space limit tests */
 | 
				
			||||||
	if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
 | 
						if (!may_expand_vm(mm, grow))
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Stack limit test */
 | 
						/* Stack limit test */
 | 
				
			||||||
| 
						 | 
					@ -1848,8 +1847,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check against address space limits *after* clearing old maps... */
 | 
						/* Check against address space limits *after* clearing old maps... */
 | 
				
			||||||
	if ((mm->total_vm << PAGE_SHIFT) + len
 | 
						if (!may_expand_vm(mm, len >> PAGE_SHIFT))
 | 
				
			||||||
	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mm->map_count > sysctl_max_map_count)
 | 
						if (mm->map_count > sysctl_max_map_count)
 | 
				
			||||||
| 
						 | 
					@ -2019,3 +2017,19 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return new_vma;
 | 
						return new_vma;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return true if the calling process may expand its vm space by the passed
 | 
				
			||||||
 | 
					 * number of pages
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int may_expand_vm(struct mm_struct *mm, unsigned long npages)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long cur = mm->total_vm;	/* pages */
 | 
				
			||||||
 | 
						unsigned long lim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cur + npages > lim)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -347,10 +347,10 @@ unsigned long do_mremap(unsigned long addr,
 | 
				
			||||||
		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 | 
							if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ret = -ENOMEM;
 | 
						if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) {
 | 
				
			||||||
	if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
 | 
							ret = -ENOMEM;
 | 
				
			||||||
	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
 | 
					 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vma->vm_flags & VM_ACCOUNT) {
 | 
						if (vma->vm_flags & VM_ACCOUNT) {
 | 
				
			||||||
		charged = (new_len - old_len) >> PAGE_SHIFT;
 | 
							charged = (new_len - old_len) >> PAGE_SHIFT;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue