diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -571,6 +571,9 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
571 | struct vm_area_struct *prev = NULL; | 571 | struct vm_area_struct *prev = NULL; |
572 | unsigned long vm_flags; | 572 | unsigned long vm_flags; |
573 | unsigned long stack_base; | 573 | unsigned long stack_base; |
574 | unsigned long stack_size; | ||
575 | unsigned long stack_expand; | ||
576 | unsigned long rlim_stack; | ||
574 | 577 | ||
575 | #ifdef CONFIG_STACK_GROWSUP | 578 | #ifdef CONFIG_STACK_GROWSUP |
576 | /* Limit stack size to 1GB */ | 579 | /* Limit stack size to 1GB */ |
@@ -627,10 +630,24 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
627 | goto out_unlock; | 630 | goto out_unlock; |
628 | } | 631 | } |
629 | 632 | ||
633 | stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE; | ||
634 | stack_size = vma->vm_end - vma->vm_start; | ||
635 | /* | ||
636 | * Align this down to a page boundary as expand_stack | ||
637 | * will align it up. | ||
638 | */ | ||
639 | rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK; | ||
640 | rlim_stack = min(rlim_stack, stack_size); | ||
630 | #ifdef CONFIG_STACK_GROWSUP | 641 | #ifdef CONFIG_STACK_GROWSUP |
631 | stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE; | 642 | if (stack_size + stack_expand > rlim_stack) |
643 | stack_base = vma->vm_start + rlim_stack; | ||
644 | else | ||
645 | stack_base = vma->vm_end + stack_expand; | ||
632 | #else | 646 | #else |
633 | stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE; | 647 | if (stack_size + stack_expand > rlim_stack) |
648 | stack_base = vma->vm_end - rlim_stack; | ||
649 | else | ||
650 | stack_base = vma->vm_start - stack_expand; | ||
634 | #endif | 651 | #endif |
635 | ret = expand_stack(vma, stack_base); | 652 | ret = expand_stack(vma, stack_base); |
636 | if (ret) | 653 | if (ret) |