diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 157 |
1 files changed, 22 insertions, 135 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 4628c42ca892..41a958a7585e 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -134,8 +134,7 @@ static int padzero(unsigned long elf_bss) | |||
134 | 134 | ||
135 | static int | 135 | static int |
136 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | 136 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, |
137 | int interp_aout, unsigned long load_addr, | 137 | unsigned long load_addr, unsigned long interp_load_addr) |
138 | unsigned long interp_load_addr) | ||
139 | { | 138 | { |
140 | unsigned long p = bprm->p; | 139 | unsigned long p = bprm->p; |
141 | int argc = bprm->argc; | 140 | int argc = bprm->argc; |
@@ -223,12 +222,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
223 | 222 | ||
224 | sp = STACK_ADD(p, ei_index); | 223 | sp = STACK_ADD(p, ei_index); |
225 | 224 | ||
226 | items = (argc + 1) + (envc + 1); | 225 | items = (argc + 1) + (envc + 1) + 1; |
227 | if (interp_aout) { | ||
228 | items += 3; /* a.out interpreters require argv & envp too */ | ||
229 | } else { | ||
230 | items += 1; /* ELF interpreters only put argc on the stack */ | ||
231 | } | ||
232 | bprm->p = STACK_ROUND(sp, items); | 226 | bprm->p = STACK_ROUND(sp, items); |
233 | 227 | ||
234 | /* Point sp at the lowest address on the stack */ | 228 | /* Point sp at the lowest address on the stack */ |
@@ -251,16 +245,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
251 | /* Now, let's put argc (and argv, envp if appropriate) on the stack */ | 245 | /* Now, let's put argc (and argv, envp if appropriate) on the stack */ |
252 | if (__put_user(argc, sp++)) | 246 | if (__put_user(argc, sp++)) |
253 | return -EFAULT; | 247 | return -EFAULT; |
254 | if (interp_aout) { | 248 | argv = sp; |
255 | argv = sp + 2; | 249 | envp = argv + argc + 1; |
256 | envp = argv + argc + 1; | ||
257 | if (__put_user((elf_addr_t)(unsigned long)argv, sp++) || | ||
258 | __put_user((elf_addr_t)(unsigned long)envp, sp++)) | ||
259 | return -EFAULT; | ||
260 | } else { | ||
261 | argv = sp; | ||
262 | envp = argv + argc + 1; | ||
263 | } | ||
264 | 250 | ||
265 | /* Populate argv and envp */ | 251 | /* Populate argv and envp */ |
266 | p = current->mm->arg_end = current->mm->arg_start; | 252 | p = current->mm->arg_end = current->mm->arg_start; |
@@ -513,59 +499,12 @@ out: | |||
513 | return error; | 499 | return error; |
514 | } | 500 | } |
515 | 501 | ||
516 | static unsigned long load_aout_interp(struct exec *interp_ex, | ||
517 | struct file *interpreter) | ||
518 | { | ||
519 | unsigned long text_data, elf_entry = ~0UL; | ||
520 | char __user * addr; | ||
521 | loff_t offset; | ||
522 | |||
523 | current->mm->end_code = interp_ex->a_text; | ||
524 | text_data = interp_ex->a_text + interp_ex->a_data; | ||
525 | current->mm->end_data = text_data; | ||
526 | current->mm->brk = interp_ex->a_bss + text_data; | ||
527 | |||
528 | switch (N_MAGIC(*interp_ex)) { | ||
529 | case OMAGIC: | ||
530 | offset = 32; | ||
531 | addr = (char __user *)0; | ||
532 | break; | ||
533 | case ZMAGIC: | ||
534 | case QMAGIC: | ||
535 | offset = N_TXTOFF(*interp_ex); | ||
536 | addr = (char __user *)N_TXTADDR(*interp_ex); | ||
537 | break; | ||
538 | default: | ||
539 | goto out; | ||
540 | } | ||
541 | |||
542 | down_write(¤t->mm->mmap_sem); | ||
543 | do_brk(0, text_data); | ||
544 | up_write(¤t->mm->mmap_sem); | ||
545 | if (!interpreter->f_op || !interpreter->f_op->read) | ||
546 | goto out; | ||
547 | if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) | ||
548 | goto out; | ||
549 | flush_icache_range((unsigned long)addr, | ||
550 | (unsigned long)addr + text_data); | ||
551 | |||
552 | down_write(¤t->mm->mmap_sem); | ||
553 | do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), | ||
554 | interp_ex->a_bss); | ||
555 | up_write(¤t->mm->mmap_sem); | ||
556 | elf_entry = interp_ex->a_entry; | ||
557 | |||
558 | out: | ||
559 | return elf_entry; | ||
560 | } | ||
561 | |||
562 | /* | 502 | /* |
563 | * These are the functions used to load ELF style executables and shared | 503 | * These are the functions used to load ELF style executables and shared |
564 | * libraries. There is no binary dependent code anywhere else. | 504 | * libraries. There is no binary dependent code anywhere else. |
565 | */ | 505 | */ |
566 | 506 | ||
567 | #define INTERPRETER_NONE 0 | 507 | #define INTERPRETER_NONE 0 |
568 | #define INTERPRETER_AOUT 1 | ||
569 | #define INTERPRETER_ELF 2 | 508 | #define INTERPRETER_ELF 2 |
570 | 509 | ||
571 | #ifndef STACK_RND_MASK | 510 | #ifndef STACK_RND_MASK |
@@ -594,7 +533,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
594 | unsigned long load_addr = 0, load_bias = 0; | 533 | unsigned long load_addr = 0, load_bias = 0; |
595 | int load_addr_set = 0; | 534 | int load_addr_set = 0; |
596 | char * elf_interpreter = NULL; | 535 | char * elf_interpreter = NULL; |
597 | unsigned int interpreter_type = INTERPRETER_NONE; | ||
598 | unsigned long error; | 536 | unsigned long error; |
599 | struct elf_phdr *elf_ppnt, *elf_phdata; | 537 | struct elf_phdr *elf_ppnt, *elf_phdata; |
600 | unsigned long elf_bss, elf_brk; | 538 | unsigned long elf_bss, elf_brk; |
@@ -605,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
605 | unsigned long interp_load_addr = 0; | 543 | unsigned long interp_load_addr = 0; |
606 | unsigned long start_code, end_code, start_data, end_data; | 544 | unsigned long start_code, end_code, start_data, end_data; |
607 | unsigned long reloc_func_desc = 0; | 545 | unsigned long reloc_func_desc = 0; |
608 | char passed_fileno[6]; | ||
609 | struct files_struct *files; | 546 | struct files_struct *files; |
610 | int executable_stack = EXSTACK_DEFAULT; | 547 | int executable_stack = EXSTACK_DEFAULT; |
611 | unsigned long def_flags = 0; | 548 | unsigned long def_flags = 0; |
@@ -774,59 +711,18 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
774 | 711 | ||
775 | /* Some simple consistency checks for the interpreter */ | 712 | /* Some simple consistency checks for the interpreter */ |
776 | if (elf_interpreter) { | 713 | if (elf_interpreter) { |
777 | static int warn; | ||
778 | interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; | ||
779 | |||
780 | /* Now figure out which format our binary is */ | ||
781 | if ((N_MAGIC(loc->interp_ex) != OMAGIC) && | ||
782 | (N_MAGIC(loc->interp_ex) != ZMAGIC) && | ||
783 | (N_MAGIC(loc->interp_ex) != QMAGIC)) | ||
784 | interpreter_type = INTERPRETER_ELF; | ||
785 | |||
786 | if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) | ||
787 | interpreter_type &= ~INTERPRETER_ELF; | ||
788 | |||
789 | if (interpreter_type == INTERPRETER_AOUT && warn < 10) { | ||
790 | printk(KERN_WARNING "a.out ELF interpreter %s is " | ||
791 | "deprecated and will not be supported " | ||
792 | "after Linux 2.6.25\n", elf_interpreter); | ||
793 | warn++; | ||
794 | } | ||
795 | |||
796 | retval = -ELIBBAD; | 714 | retval = -ELIBBAD; |
797 | if (!interpreter_type) | 715 | /* Not an ELF interpreter */ |
716 | if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) | ||
798 | goto out_free_dentry; | 717 | goto out_free_dentry; |
799 | |||
800 | /* Make sure only one type was selected */ | ||
801 | if ((interpreter_type & INTERPRETER_ELF) && | ||
802 | interpreter_type != INTERPRETER_ELF) { | ||
803 | // FIXME - ratelimit this before re-enabling | ||
804 | // printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n"); | ||
805 | interpreter_type = INTERPRETER_ELF; | ||
806 | } | ||
807 | /* Verify the interpreter has a valid arch */ | 718 | /* Verify the interpreter has a valid arch */ |
808 | if ((interpreter_type == INTERPRETER_ELF) && | 719 | if (!elf_check_arch(&loc->interp_elf_ex)) |
809 | !elf_check_arch(&loc->interp_elf_ex)) | ||
810 | goto out_free_dentry; | 720 | goto out_free_dentry; |
811 | } else { | 721 | } else { |
812 | /* Executables without an interpreter also need a personality */ | 722 | /* Executables without an interpreter also need a personality */ |
813 | SET_PERSONALITY(loc->elf_ex, 0); | 723 | SET_PERSONALITY(loc->elf_ex, 0); |
814 | } | 724 | } |
815 | 725 | ||
816 | /* OK, we are done with that, now set up the arg stuff, | ||
817 | and then start this sucker up */ | ||
818 | if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { | ||
819 | char *passed_p = passed_fileno; | ||
820 | sprintf(passed_fileno, "%d", elf_exec_fileno); | ||
821 | |||
822 | if (elf_interpreter) { | ||
823 | retval = copy_strings_kernel(1, &passed_p, bprm); | ||
824 | if (retval) | ||
825 | goto out_free_dentry; | ||
826 | bprm->argc++; | ||
827 | } | ||
828 | } | ||
829 | |||
830 | /* Flush all traces of the currently running executable */ | 726 | /* Flush all traces of the currently running executable */ |
831 | retval = flush_old_exec(bprm); | 727 | retval = flush_old_exec(bprm); |
832 | if (retval) | 728 | if (retval) |
@@ -1004,24 +900,19 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1004 | } | 900 | } |
1005 | 901 | ||
1006 | if (elf_interpreter) { | 902 | if (elf_interpreter) { |
1007 | if (interpreter_type == INTERPRETER_AOUT) { | 903 | unsigned long uninitialized_var(interp_map_addr); |
1008 | elf_entry = load_aout_interp(&loc->interp_ex, | 904 | |
1009 | interpreter); | 905 | elf_entry = load_elf_interp(&loc->interp_elf_ex, |
1010 | } else { | 906 | interpreter, |
1011 | unsigned long uninitialized_var(interp_map_addr); | 907 | &interp_map_addr, |
1012 | 908 | load_bias); | |
1013 | elf_entry = load_elf_interp(&loc->interp_elf_ex, | 909 | if (!IS_ERR((void *)elf_entry)) { |
1014 | interpreter, | 910 | /* |
1015 | &interp_map_addr, | 911 | * load_elf_interp() returns relocation |
1016 | load_bias); | 912 | * adjustment |
1017 | if (!IS_ERR((void *)elf_entry)) { | 913 | */ |
1018 | /* | 914 | interp_load_addr = elf_entry; |
1019 | * load_elf_interp() returns relocation | 915 | elf_entry += loc->interp_elf_ex.e_entry; |
1020 | * adjustment | ||
1021 | */ | ||
1022 | interp_load_addr = elf_entry; | ||
1023 | elf_entry += loc->interp_elf_ex.e_entry; | ||
1024 | } | ||
1025 | } | 916 | } |
1026 | if (BAD_ADDR(elf_entry)) { | 917 | if (BAD_ADDR(elf_entry)) { |
1027 | force_sig(SIGSEGV, current); | 918 | force_sig(SIGSEGV, current); |
@@ -1045,8 +936,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1045 | 936 | ||
1046 | kfree(elf_phdata); | 937 | kfree(elf_phdata); |
1047 | 938 | ||
1048 | if (interpreter_type != INTERPRETER_AOUT) | 939 | sys_close(elf_exec_fileno); |
1049 | sys_close(elf_exec_fileno); | ||
1050 | 940 | ||
1051 | set_binfmt(&elf_format); | 941 | set_binfmt(&elf_format); |
1052 | 942 | ||
@@ -1061,15 +951,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1061 | compute_creds(bprm); | 951 | compute_creds(bprm); |
1062 | current->flags &= ~PF_FORKNOEXEC; | 952 | current->flags &= ~PF_FORKNOEXEC; |
1063 | retval = create_elf_tables(bprm, &loc->elf_ex, | 953 | retval = create_elf_tables(bprm, &loc->elf_ex, |
1064 | (interpreter_type == INTERPRETER_AOUT), | ||
1065 | load_addr, interp_load_addr); | 954 | load_addr, interp_load_addr); |
1066 | if (retval < 0) { | 955 | if (retval < 0) { |
1067 | send_sig(SIGKILL, current, 0); | 956 | send_sig(SIGKILL, current, 0); |
1068 | goto out; | 957 | goto out; |
1069 | } | 958 | } |
1070 | /* N.B. passed_fileno might not be initialized? */ | 959 | /* N.B. passed_fileno might not be initialized? */ |
1071 | if (interpreter_type == INTERPRETER_AOUT) | ||
1072 | current->mm->arg_start += strlen(passed_fileno) + 1; | ||
1073 | current->mm->end_code = end_code; | 960 | current->mm->end_code = end_code; |
1074 | current->mm->start_code = start_code; | 961 | current->mm->start_code = start_code; |
1075 | current->mm->start_data = start_data; | 962 | current->mm->start_data = start_data; |
@@ -1077,7 +964,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1077 | current->mm->start_stack = bprm->p; | 964 | current->mm->start_stack = bprm->p; |
1078 | 965 | ||
1079 | #ifdef arch_randomize_brk | 966 | #ifdef arch_randomize_brk |
1080 | if (current->flags & PF_RANDOMIZE) | 967 | if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) |
1081 | current->mm->brk = current->mm->start_brk = | 968 | current->mm->brk = current->mm->start_brk = |
1082 | arch_randomize_brk(current->mm); | 969 | arch_randomize_brk(current->mm); |
1083 | #endif | 970 | #endif |