aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-01-29 01:14:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-01-29 11:22:01 -0500
commit221af7f87b97431e3ee21ce4b0e77d5411cf1549 (patch)
tree480126aada06d87c09cb62e7c8fa292572438c18 /fs
parent64a028a6de08545a2c94f302bc7694bf48aee5b5 (diff)
Split 'flush_old_exec' into two functions
'flush_old_exec()' is the point of no return when doing an execve(), and it is pretty badly misnamed. It doesn't just flush the old executable environment, it also starts up the new one. Which is very inconvenient for things like setting up the new personality, because we want the new personality to affect the starting of the new environment, but at the same time we do _not_ want the new personality to take effect if flushing the old one fails. As a result, the x86-64 '32-bit' personality is actually done using this insane "I'm going to change the ABI, but I haven't done it yet" bit (TIF_ABI_PENDING), with SET_PERSONALITY() not actually setting the personality, but just the "pending" bit, so that "flush_thread()" can do the actual personality magic. This patch in no way changes any of that insanity, but it does split the 'flush_old_exec()' function up into a preparatory part that can fail (still called flush_old_exec()), and a new part that will actually set up the new exec environment (setup_new_exec()). All callers are changed to trivially comply with the new world order. Signed-off-by: H. Peter Anvin <hpa@zytor.com> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_aout.c1
-rw-r--r--fs/binfmt_elf.c27
-rw-r--r--fs/binfmt_elf_fdpic.c3
-rw-r--r--fs/binfmt_flat.c1
-rw-r--r--fs/binfmt_som.c1
-rw-r--r--fs/exec.c26
6 files changed, 24 insertions, 35 deletions
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 346b69405363..fdd397099172 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -264,6 +264,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
264#else 264#else
265 set_personality(PER_LINUX); 265 set_personality(PER_LINUX);
266#endif 266#endif
267 setup_new_exec(bprm);
267 268
268 current->mm->end_code = ex.a_text + 269 current->mm->end_code = ex.a_text +
269 (current->mm->start_code = N_TXTADDR(ex)); 270 (current->mm->start_code = N_TXTADDR(ex));
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index edd90c49003c..fd5b2ea5d299 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -662,27 +662,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
662 if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') 662 if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
663 goto out_free_interp; 663 goto out_free_interp;
664 664
665 /*
666 * The early SET_PERSONALITY here is so that the lookup
667 * for the interpreter happens in the namespace of the
668 * to-be-execed image. SET_PERSONALITY can select an
669 * alternate root.
670 *
671 * However, SET_PERSONALITY is NOT allowed to switch
672 * this task into the new images's memory mapping
673 * policy - that is, TASK_SIZE must still evaluate to
674 * that which is appropriate to the execing application.
675 * This is because exit_mmap() needs to have TASK_SIZE
676 * evaluate to the size of the old image.
677 *
678 * So if (say) a 64-bit application is execing a 32-bit
679 * application it is the architecture's responsibility
680 * to defer changing the value of TASK_SIZE until the
681 * switch really is going to happen - do this in
682 * flush_thread(). - akpm
683 */
684 SET_PERSONALITY(loc->elf_ex);
685
686 interpreter = open_exec(elf_interpreter); 665 interpreter = open_exec(elf_interpreter);
687 retval = PTR_ERR(interpreter); 666 retval = PTR_ERR(interpreter);
688 if (IS_ERR(interpreter)) 667 if (IS_ERR(interpreter))
@@ -730,9 +709,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
730 /* Verify the interpreter has a valid arch */ 709 /* Verify the interpreter has a valid arch */
731 if (!elf_check_arch(&loc->interp_elf_ex)) 710 if (!elf_check_arch(&loc->interp_elf_ex))
732 goto out_free_dentry; 711 goto out_free_dentry;
733 } else {
734 /* Executables without an interpreter also need a personality */
735 SET_PERSONALITY(loc->elf_ex);
736 } 712 }
737 713
738 /* Flush all traces of the currently running executable */ 714 /* Flush all traces of the currently running executable */
@@ -752,7 +728,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
752 728
753 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 729 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
754 current->flags |= PF_RANDOMIZE; 730 current->flags |= PF_RANDOMIZE;
755 arch_pick_mmap_layout(current->mm); 731
732 setup_new_exec(bprm);
756 733
757 /* Do this so that we can load the interpreter, if need be. We will 734 /* Do this so that we can load the interpreter, if need be. We will
758 change some of these later */ 735 change some of these later */
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index c57d9ce5ff7e..18d77297ccc8 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -321,6 +321,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
321 set_personality(PER_LINUX_FDPIC); 321 set_personality(PER_LINUX_FDPIC);
322 if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) 322 if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
323 current->personality |= READ_IMPLIES_EXEC; 323 current->personality |= READ_IMPLIES_EXEC;
324
325 setup_new_exec(bprm);
326
324 set_binfmt(&elf_fdpic_format); 327 set_binfmt(&elf_fdpic_format);
325 328
326 current->mm->start_code = 0; 329 current->mm->start_code = 0;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index d4a00ea1054c..42c6b4a54445 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -519,6 +519,7 @@ static int load_flat_file(struct linux_binprm * bprm,
519 519
520 /* OK, This is the point of no return */ 520 /* OK, This is the point of no return */
521 set_personality(PER_LINUX_32BIT); 521 set_personality(PER_LINUX_32BIT);
522 setup_new_exec(bprm);
522 } 523 }
523 524
524 /* 525 /*
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 2a9b5330cc5e..cc8560f6c9b0 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -227,6 +227,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
227 /* OK, This is the point of no return */ 227 /* OK, This is the point of no return */
228 current->flags &= ~PF_FORKNOEXEC; 228 current->flags &= ~PF_FORKNOEXEC;
229 current->personality = PER_HPUX; 229 current->personality = PER_HPUX;
230 setup_new_exec(bprm);
230 231
231 /* Set the task size for HP-UX processes such that 232 /* Set the task size for HP-UX processes such that
232 * the gateway page is outside the address space. 233 * the gateway page is outside the address space.
diff --git a/fs/exec.c b/fs/exec.c
index 632b02e34ec7..675c3f44c2ea 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -941,9 +941,7 @@ void set_task_comm(struct task_struct *tsk, char *buf)
941 941
942int flush_old_exec(struct linux_binprm * bprm) 942int flush_old_exec(struct linux_binprm * bprm)
943{ 943{
944 char * name; 944 int retval;
945 int i, ch, retval;
946 char tcomm[sizeof(current->comm)];
947 945
948 /* 946 /*
949 * Make sure we have a private signal table and that 947 * Make sure we have a private signal table and that
@@ -963,6 +961,20 @@ int flush_old_exec(struct linux_binprm * bprm)
963 goto out; 961 goto out;
964 962
965 bprm->mm = NULL; /* We're using it now */ 963 bprm->mm = NULL; /* We're using it now */
964 return 0;
965
966out:
967 return retval;
968}
969EXPORT_SYMBOL(flush_old_exec);
970
971void setup_new_exec(struct linux_binprm * bprm)
972{
973 int i, ch;
974 char * name;
975 char tcomm[sizeof(current->comm)];
976
977 arch_pick_mmap_layout(current->mm);
966 978
967 /* This is the point of no return */ 979 /* This is the point of no return */
968 current->sas_ss_sp = current->sas_ss_size = 0; 980 current->sas_ss_sp = current->sas_ss_size = 0;
@@ -1019,14 +1031,8 @@ int flush_old_exec(struct linux_binprm * bprm)
1019 1031
1020 flush_signal_handlers(current, 0); 1032 flush_signal_handlers(current, 0);
1021 flush_old_files(current->files); 1033 flush_old_files(current->files);
1022
1023 return 0;
1024
1025out:
1026 return retval;
1027} 1034}
1028 1035EXPORT_SYMBOL(setup_new_exec);
1029EXPORT_SYMBOL(flush_old_exec);
1030 1036
1031/* 1037/*
1032 * Prepare credentials and lock ->cred_guard_mutex. 1038 * Prepare credentials and lock ->cred_guard_mutex.