diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 57 |
1 files changed, 40 insertions, 17 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) |
@@ -941,9 +958,7 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
941 | 958 | ||
942 | int flush_old_exec(struct linux_binprm * bprm) | 959 | int flush_old_exec(struct linux_binprm * bprm) |
943 | { | 960 | { |
944 | char * name; | 961 | int retval; |
945 | int i, ch, retval; | ||
946 | char tcomm[sizeof(current->comm)]; | ||
947 | 962 | ||
948 | /* | 963 | /* |
949 | * Make sure we have a private signal table and that | 964 | * Make sure we have a private signal table and that |
@@ -964,6 +979,25 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
964 | 979 | ||
965 | bprm->mm = NULL; /* We're using it now */ | 980 | bprm->mm = NULL; /* We're using it now */ |
966 | 981 | ||
982 | current->flags &= ~PF_RANDOMIZE; | ||
983 | flush_thread(); | ||
984 | current->personality &= ~bprm->per_clear; | ||
985 | |||
986 | return 0; | ||
987 | |||
988 | out: | ||
989 | return retval; | ||
990 | } | ||
991 | EXPORT_SYMBOL(flush_old_exec); | ||
992 | |||
993 | void setup_new_exec(struct linux_binprm * bprm) | ||
994 | { | ||
995 | int i, ch; | ||
996 | char * name; | ||
997 | char tcomm[sizeof(current->comm)]; | ||
998 | |||
999 | arch_pick_mmap_layout(current->mm); | ||
1000 | |||
967 | /* This is the point of no return */ | 1001 | /* This is the point of no return */ |
968 | current->sas_ss_sp = current->sas_ss_size = 0; | 1002 | current->sas_ss_sp = current->sas_ss_size = 0; |
969 | 1003 | ||
@@ -985,9 +1019,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
985 | tcomm[i] = '\0'; | 1019 | tcomm[i] = '\0'; |
986 | set_task_comm(current, tcomm); | 1020 | set_task_comm(current, tcomm); |
987 | 1021 | ||
988 | current->flags &= ~PF_RANDOMIZE; | ||
989 | flush_thread(); | ||
990 | |||
991 | /* Set the new mm task size. We have to do that late because it may | 1022 | /* Set the new mm task size. We have to do that late because it may |
992 | * depend on TIF_32BIT which is only updated in flush_thread() on | 1023 | * depend on TIF_32BIT which is only updated in flush_thread() on |
993 | * some architectures like powerpc | 1024 | * some architectures like powerpc |
@@ -1003,8 +1034,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1003 | set_dumpable(current->mm, suid_dumpable); | 1034 | set_dumpable(current->mm, suid_dumpable); |
1004 | } | 1035 | } |
1005 | 1036 | ||
1006 | current->personality &= ~bprm->per_clear; | ||
1007 | |||
1008 | /* | 1037 | /* |
1009 | * Flush performance counters when crossing a | 1038 | * Flush performance counters when crossing a |
1010 | * security domain: | 1039 | * security domain: |
@@ -1019,14 +1048,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1019 | 1048 | ||
1020 | flush_signal_handlers(current, 0); | 1049 | flush_signal_handlers(current, 0); |
1021 | flush_old_files(current->files); | 1050 | flush_old_files(current->files); |
1022 | |||
1023 | return 0; | ||
1024 | |||
1025 | out: | ||
1026 | return retval; | ||
1027 | } | 1051 | } |
1028 | 1052 | EXPORT_SYMBOL(setup_new_exec); | |
1029 | EXPORT_SYMBOL(flush_old_exec); | ||
1030 | 1053 | ||
1031 | /* | 1054 | /* |
1032 | * Prepare credentials and lock ->cred_guard_mutex. | 1055 | * Prepare credentials and lock ->cred_guard_mutex. |