diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 56 |
1 files changed, 39 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,23 @@ 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; | ||
630 | #ifdef CONFIG_STACK_GROWSUP | 640 | #ifdef CONFIG_STACK_GROWSUP |
631 | stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE; | 641 | if (stack_size + stack_expand > rlim_stack) |
642 | stack_base = vma->vm_start + rlim_stack; | ||
643 | else | ||
644 | stack_base = vma->vm_end + stack_expand; | ||
632 | #else | 645 | #else |
633 | stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE; | 646 | if (stack_size + stack_expand > rlim_stack) |
647 | stack_base = vma->vm_end - rlim_stack; | ||
648 | else | ||
649 | stack_base = vma->vm_start - stack_expand; | ||
634 | #endif | 650 | #endif |
635 | ret = expand_stack(vma, stack_base); | 651 | ret = expand_stack(vma, stack_base); |
636 | if (ret) | 652 | if (ret) |
@@ -941,9 +957,7 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
941 | 957 | ||
942 | int flush_old_exec(struct linux_binprm * bprm) | 958 | int flush_old_exec(struct linux_binprm * bprm) |
943 | { | 959 | { |
944 | char * name; | 960 | int retval; |
945 | int i, ch, retval; | ||
946 | char tcomm[sizeof(current->comm)]; | ||
947 | 961 | ||
948 | /* | 962 | /* |
949 | * Make sure we have a private signal table and that | 963 | * Make sure we have a private signal table and that |
@@ -964,6 +978,25 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
964 | 978 | ||
965 | bprm->mm = NULL; /* We're using it now */ | 979 | bprm->mm = NULL; /* We're using it now */ |
966 | 980 | ||
981 | current->flags &= ~PF_RANDOMIZE; | ||
982 | flush_thread(); | ||
983 | current->personality &= ~bprm->per_clear; | ||
984 | |||
985 | return 0; | ||
986 | |||
987 | out: | ||
988 | return retval; | ||
989 | } | ||
990 | EXPORT_SYMBOL(flush_old_exec); | ||
991 | |||
992 | void setup_new_exec(struct linux_binprm * bprm) | ||
993 | { | ||
994 | int i, ch; | ||
995 | char * name; | ||
996 | char tcomm[sizeof(current->comm)]; | ||
997 | |||
998 | arch_pick_mmap_layout(current->mm); | ||
999 | |||
967 | /* This is the point of no return */ | 1000 | /* This is the point of no return */ |
968 | current->sas_ss_sp = current->sas_ss_size = 0; | 1001 | current->sas_ss_sp = current->sas_ss_size = 0; |
969 | 1002 | ||
@@ -985,9 +1018,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
985 | tcomm[i] = '\0'; | 1018 | tcomm[i] = '\0'; |
986 | set_task_comm(current, tcomm); | 1019 | set_task_comm(current, tcomm); |
987 | 1020 | ||
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 | 1021 | /* 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 | 1022 | * depend on TIF_32BIT which is only updated in flush_thread() on |
993 | * some architectures like powerpc | 1023 | * some architectures like powerpc |
@@ -1003,8 +1033,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1003 | set_dumpable(current->mm, suid_dumpable); | 1033 | set_dumpable(current->mm, suid_dumpable); |
1004 | } | 1034 | } |
1005 | 1035 | ||
1006 | current->personality &= ~bprm->per_clear; | ||
1007 | |||
1008 | /* | 1036 | /* |
1009 | * Flush performance counters when crossing a | 1037 | * Flush performance counters when crossing a |
1010 | * security domain: | 1038 | * security domain: |
@@ -1019,14 +1047,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1019 | 1047 | ||
1020 | flush_signal_handlers(current, 0); | 1048 | flush_signal_handlers(current, 0); |
1021 | flush_old_files(current->files); | 1049 | flush_old_files(current->files); |
1022 | |||
1023 | return 0; | ||
1024 | |||
1025 | out: | ||
1026 | return retval; | ||
1027 | } | 1050 | } |
1028 | 1051 | EXPORT_SYMBOL(setup_new_exec); | |
1029 | EXPORT_SYMBOL(flush_old_exec); | ||
1030 | 1052 | ||
1031 | /* | 1053 | /* |
1032 | * Prepare credentials and lock ->cred_guard_mutex. | 1054 | * Prepare credentials and lock ->cred_guard_mutex. |