[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
@ -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 **,
|
||||
unsigned long addr, unsigned long len, pgoff_t pgoff);
|
||||
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);
|
||||
|
||||
|
24
mm/mmap.c
24
mm/mmap.c
@ -1009,8 +1009,7 @@ munmap_back:
|
||||
}
|
||||
|
||||
/* Check against address space limit. */
|
||||
if ((mm->total_vm << PAGE_SHIFT) + len
|
||||
> current->signal->rlim[RLIMIT_AS].rlim_cur)
|
||||
if (!may_expand_vm(mm, len >> PAGE_SHIFT))
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
|
||||
/* address space limit tests */
|
||||
if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
|
||||
if (!may_expand_vm(mm, grow))
|
||||
return -ENOMEM;
|
||||
|
||||
/* 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... */
|
||||
if ((mm->total_vm << PAGE_SHIFT) + len
|
||||
> current->signal->rlim[RLIMIT_AS].rlim_cur)
|
||||
if (!may_expand_vm(mm, len >> PAGE_SHIFT))
|
||||
return -ENOMEM;
|
||||
|
||||
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 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))
|
||||
goto out;
|
||||
}
|
||||
ret = -ENOMEM;
|
||||
if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
|
||||
> current->signal->rlim[RLIMIT_AS].rlim_cur)
|
||||
if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vma->vm_flags & VM_ACCOUNT) {
|
||||
charged = (new_len - old_len) >> PAGE_SHIFT;
|
||||
|
Loading…
Reference in New Issue
Block a user