diff --git a/mm/memory.c b/mm/memory.c index b6e5fd2..9dcef72 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2760,21 +2760,35 @@ out_release: } /* - * This is like a special single-page "expand_downwards()", - * except we must first make sure that 'address-PAGE_SIZE' + * This is like a special single-page "expand_{down|up}wards()", + * 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; + struct vm_area_struct *v; + + if (vma->vm_flags & VM_GROWSDOWN) { + address &= PAGE_MASK; + if (address == vma->vm_start) { + address -= PAGE_SIZE; + if (find_vma(vma->vm_mm, address) != vma) + return -ENOMEM; - expand_stack(vma, address); + expand_stack(vma, address); + } + } else if (vma->vm_flags & VM_GROWSUP) { + address = PAGE_ALIGN(address + 1); + if (address == vma->vm_end) { + address += PAGE_SIZE; + if ((v = find_vma(vma->vm_mm, address)) && + v->vm_start <= address) { + return -ENOMEM; + } + expand_upwards(vma, address); + } } return 0; }