View | Details | Raw Unified
Collapse All | Expand All

(-) linux-2.6.10/mm/mmap.c (-42 / +77 lines)
 Lines 1319-1331   out: Link Here 
	return prev ? prev->vm_next : vma;
	return prev ? prev->vm_next : vma;
}
}
/*
 * Verify that the stack growth is acceptable and
 * update accounting. This is shared with both the
 * grow-up and grow-down cases.
 */
static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, unsigned long grow)
{
	struct mm_struct *mm = vma->vm_mm;
	struct rlimit *rlim = current->signal->rlim;
	/* address space limit tests */
	rlim = current->signal->rlim;
	if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
		return -ENOMEM;
	/* Stack limit test */
	if (size > rlim[RLIMIT_STACK].rlim_cur)
		return -ENOMEM;
	/* mlock limit tests */
	if (vma->vm_flags & VM_LOCKED) {
		unsigned long locked;
		unsigned long limit;
		locked = mm->locked_vm + grow;
		limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
		if (locked > limit && !capable(CAP_IPC_LOCK))
			return -ENOMEM;
	}
	/*
	 * Overcommit..  This must be the final test, as it will
	 * update security statistics.
	 */
	if (security_vm_enough_memory(grow))
		return -ENOMEM;
	/* Ok, everything looks good - let it rip */
	mm->total_vm += grow;
	if (vma->vm_flags & VM_LOCKED)
		mm->locked_vm += grow;
	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
	return 0;
}
#ifdef CONFIG_STACK_GROWSUP
#ifdef CONFIG_STACK_GROWSUP
/*
/*
 * vma is the first one with address > vma->vm_end.  Have to extend vma.
 * vma is the first one with address > vma->vm_end.  Have to extend vma.
 */
 */
int expand_stack(struct vm_area_struct * vma, unsigned long address)
int expand_stack(struct vm_area_struct * vma, unsigned long address)
{
{
	unsigned long grow;
	int error;
	if (!(vma->vm_flags & VM_GROWSUP))
	if (!(vma->vm_flags & VM_GROWSUP))
		return -EFAULT;
		return -EFAULT;
 Lines 1345-1372   int expand_stack(struct vm_area_struct * Link Here 
	 */
	 */
	address += 4 + PAGE_SIZE - 1;
	address += 4 + PAGE_SIZE - 1;
	address &= PAGE_MASK;
	address &= PAGE_MASK;
	grow = (address - vma->vm_end) >> PAGE_SHIFT;
	error = 0;
	/* Overcommit.. */
	/* Somebody else might have raced and expanded it already */
	if (security_vm_enough_memory(grow)) {
	if (address > vma->vm_end) {
		anon_vma_unlock(vma);
		unsigned long size, grow;
		return -ENOMEM;
	}
		size = address - vma->vm_start;
	
		grow = (address - vma->vm_end) >> PAGE_SHIFT;
	if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
			((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
		error = acct_stack_growth(vma, size, grow);
			current->signal->rlim[RLIMIT_AS].rlim_cur) {
		if (!error)
		anon_vma_unlock(vma);
			vma->vm_end = address;
		vm_unacct_memory(grow);
		return -ENOMEM;
	}
	}
	vma->vm_end = address;
	vma->vm_mm->total_vm += grow;
	error = acct_stack_growth(vma, size, grow);
	if (vma->vm_flags & VM_LOCKED)
	if (!error)
		vma->vm_mm->locked_vm += grow;
		vma->vm_end = address;
	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
        anon_vma_unlock(vma);
	anon_vma_unlock(vma);
	return error;
	return 0;
}
}
struct vm_area_struct *
struct vm_area_struct *
 Lines 1391-1397   find_extend_vma(struct mm_struct *mm, un Link Here 
 */
 */
int expand_stack(struct vm_area_struct *vma, unsigned long address)
int expand_stack(struct vm_area_struct *vma, unsigned long address)
{
{
	unsigned long grow;
	int error;
	/*
	/*
	 * We must make sure the anon_vma is allocated
	 * We must make sure the anon_vma is allocated
 Lines 1407-1435   int expand_stack(struct vm_area_struct * Link Here 
	 * anon_vma lock to serialize against concurrent expand_stacks.
	 * anon_vma lock to serialize against concurrent expand_stacks.
	 */
	 */
	address &= PAGE_MASK;
	address &= PAGE_MASK;
	grow = (vma->vm_start - address) >> PAGE_SHIFT;
	error = 0;
	/* Overcommit.. */
	/* Somebody else might have raced and expanded it already */
	if (security_vm_enough_memory(grow)) {
	if (address < vma->vm_start) {
		anon_vma_unlock(vma);
		unsigned long size, grow;
		return -ENOMEM;
	}
		size = vma->vm_end - address;
	
		grow = (vma->vm_start - address) >> PAGE_SHIFT;
	if (vma->vm_end - address > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
			((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
		error = acct_stack_growth(vma, size, grow);
			current->signal->rlim[RLIMIT_AS].rlim_cur) {
		if (!error) {
		anon_vma_unlock(vma);
			vma->vm_start = address;
		vm_unacct_memory(grow);
			vma->vm_pgoff -= grow;
		return -ENOMEM;
		}
	}
	}
	vma->vm_start = address;
	vma->vm_pgoff -= grow;
	vma->vm_mm->total_vm += grow;
	if (vma->vm_flags & VM_LOCKED)
		vma->vm_mm->locked_vm += grow;
	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
	anon_vma_unlock(vma);
	anon_vma_unlock(vma);
	return 0;
	return error;
}
}
struct vm_area_struct *
struct vm_area_struct *