aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2008-02-08 07:21:54 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:41 -0500
commitd20894a23708c2af75966534f8e4dedb46d48db2 (patch)
treef178118c4f1b1d248d2237f4088d2120e4f42083
parent48d13e483c5b450be451f78cc9cb43c0bdd6b7bb (diff)
Remove a.out interpreter support in ELF loader
Following the deprecation schedule the a.out ELF interpreter support is removed now with this patch. a.out ELF interpreters were an transition feature for moving a.out systems to ELF, but they're unlikely to be still needed. Pure a.out systems will still work of course. This allows to simplify the hairy ELF loader. Signed-off-by: Andi Kleen <ak@suse.de> Cc: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/feature-removal-schedule.txt11
-rw-r--r--fs/binfmt_elf.c173
2 files changed, 21 insertions, 163 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2ad5c985e204..ce9503c892b5 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -99,17 +99,6 @@ Who: Eric Biederman <ebiederm@xmission.com>
99 99
100--------------------------- 100---------------------------
101 101
102What: a.out interpreter support for ELF executables
103When: 2.6.25
104Files: fs/binfmt_elf.c
105Why: Using a.out interpreters for ELF executables was a feature for
106 transition from a.out to ELF. But now it is unlikely to be still
107 needed anymore and removing it would simplify the hairy ELF
108 loader code.
109Who: Andi Kleen <ak@suse.de>
110
111---------------------------
112
113What: remove EXPORT_SYMBOL(kernel_thread) 102What: remove EXPORT_SYMBOL(kernel_thread)
114When: August 2006 103When: August 2006
115Files: arch/*/kernel/*_ksyms.c 104Files: arch/*/kernel/*_ksyms.c
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index a93b1170551b..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
135static int 135static int
136create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, 136create_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,61 +499,6 @@ out:
513 return error; 499 return error;
514} 500}
515 501
516#ifdef CONFIG_ARCH_SUPPORTS_AOUT
517static unsigned long load_aout_interp(struct exec *interp_ex,
518 struct file *interpreter)
519{
520 unsigned long text_data, elf_entry = ~0UL;
521 char __user * addr;
522 loff_t offset;
523
524 current->mm->end_code = interp_ex->a_text;
525 text_data = interp_ex->a_text + interp_ex->a_data;
526 current->mm->end_data = text_data;
527 current->mm->brk = interp_ex->a_bss + text_data;
528
529 switch (N_MAGIC(*interp_ex)) {
530 case OMAGIC:
531 offset = 32;
532 addr = (char __user *)0;
533 break;
534 case ZMAGIC:
535 case QMAGIC:
536 offset = N_TXTOFF(*interp_ex);
537 addr = (char __user *)N_TXTADDR(*interp_ex);
538 break;
539 default:
540 goto out;
541 }
542
543 down_write(&current->mm->mmap_sem);
544 do_brk(0, text_data);
545 up_write(&current->mm->mmap_sem);
546 if (!interpreter->f_op || !interpreter->f_op->read)
547 goto out;
548 if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
549 goto out;
550 flush_icache_range((unsigned long)addr,
551 (unsigned long)addr + text_data);
552
553 down_write(&current->mm->mmap_sem);
554 do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
555 interp_ex->a_bss);
556 up_write(&current->mm->mmap_sem);
557 elf_entry = interp_ex->a_entry;
558
559out:
560 return elf_entry;
561}
562#else
563/* dummy extern - the function should never be called if !CONFIG_AOUT_BINFMT */
564static inline unsigned long load_aout_interp(struct exec *interp_ex,
565 struct file *interpreter)
566{
567 return -ELIBACC;
568}
569#endif
570
571/* 502/*
572 * 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
573 * libraries. There is no binary dependent code anywhere else. 504 * libraries. There is no binary dependent code anywhere else.
@@ -576,13 +507,6 @@ static inline unsigned long load_aout_interp(struct exec *interp_ex,
576#define INTERPRETER_NONE 0 507#define INTERPRETER_NONE 0
577#define INTERPRETER_ELF 2 508#define INTERPRETER_ELF 2
578 509
579#ifdef CONFIG_ARCH_SUPPORTS_AOUT
580#define INTERPRETER_AOUT 1
581#define IS_AOUT_INTERP(x) ((x) == INTERPRETER_AOUT)
582#else
583#define IS_AOUT_INTERP(x) (0)
584#endif
585
586#ifndef STACK_RND_MASK 510#ifndef STACK_RND_MASK
587#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */ 511#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */
588#endif 512#endif
@@ -609,7 +533,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
609 unsigned long load_addr = 0, load_bias = 0; 533 unsigned long load_addr = 0, load_bias = 0;
610 int load_addr_set = 0; 534 int load_addr_set = 0;
611 char * elf_interpreter = NULL; 535 char * elf_interpreter = NULL;
612 unsigned int interpreter_type = INTERPRETER_NONE;
613 unsigned long error; 536 unsigned long error;
614 struct elf_phdr *elf_ppnt, *elf_phdata; 537 struct elf_phdr *elf_ppnt, *elf_phdata;
615 unsigned long elf_bss, elf_brk; 538 unsigned long elf_bss, elf_brk;
@@ -620,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
620 unsigned long interp_load_addr = 0; 543 unsigned long interp_load_addr = 0;
621 unsigned long start_code, end_code, start_data, end_data; 544 unsigned long start_code, end_code, start_data, end_data;
622 unsigned long reloc_func_desc = 0; 545 unsigned long reloc_func_desc = 0;
623 char passed_fileno[6];
624 struct files_struct *files; 546 struct files_struct *files;
625 int executable_stack = EXSTACK_DEFAULT; 547 int executable_stack = EXSTACK_DEFAULT;
626 unsigned long def_flags = 0; 548 unsigned long def_flags = 0;
@@ -789,62 +711,18 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
789 711
790 /* Some simple consistency checks for the interpreter */ 712 /* Some simple consistency checks for the interpreter */
791 if (elf_interpreter) { 713 if (elf_interpreter) {
792 static int warn;
793#ifdef CONFIG_ARCH_SUPPORTS_AOUT
794 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
795
796 /* Now figure out which format our binary is */
797 if ((N_MAGIC(loc->interp_ex) != OMAGIC) &&
798 (N_MAGIC(loc->interp_ex) != ZMAGIC) &&
799 (N_MAGIC(loc->interp_ex) != QMAGIC))
800 interpreter_type = INTERPRETER_ELF;
801#else
802 interpreter_type = INTERPRETER_ELF;
803#endif
804 if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
805 interpreter_type &= ~INTERPRETER_ELF;
806
807 if (IS_AOUT_INTERP(interpreter_type) && warn < 10) {
808 printk(KERN_WARNING "a.out ELF interpreter %s is "
809 "deprecated and will not be supported "
810 "after Linux 2.6.25\n", elf_interpreter);
811 warn++;
812 }
813
814 retval = -ELIBBAD; 714 retval = -ELIBBAD;
815 if (!interpreter_type) 715 /* Not an ELF interpreter */
716 if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
816 goto out_free_dentry; 717 goto out_free_dentry;
817
818 /* Make sure only one type was selected */
819 if ((interpreter_type & INTERPRETER_ELF) &&
820 interpreter_type != INTERPRETER_ELF) {
821 // FIXME - ratelimit this before re-enabling
822 // printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n");
823 interpreter_type = INTERPRETER_ELF;
824 }
825 /* Verify the interpreter has a valid arch */ 718 /* Verify the interpreter has a valid arch */
826 if ((interpreter_type == INTERPRETER_ELF) && 719 if (!elf_check_arch(&loc->interp_elf_ex))
827 !elf_check_arch(&loc->interp_elf_ex))
828 goto out_free_dentry; 720 goto out_free_dentry;
829 } else { 721 } else {
830 /* Executables without an interpreter also need a personality */ 722 /* Executables without an interpreter also need a personality */
831 SET_PERSONALITY(loc->elf_ex, 0); 723 SET_PERSONALITY(loc->elf_ex, 0);
832 } 724 }
833 725
834 /* OK, we are done with that, now set up the arg stuff,
835 and then start this sucker up */
836 if (IS_AOUT_INTERP(interpreter_type) && !bprm->sh_bang) {
837 char *passed_p = passed_fileno;
838 sprintf(passed_fileno, "%d", elf_exec_fileno);
839
840 if (elf_interpreter) {
841 retval = copy_strings_kernel(1, &passed_p, bprm);
842 if (retval)
843 goto out_free_dentry;
844 bprm->argc++;
845 }
846 }
847
848 /* Flush all traces of the currently running executable */ 726 /* Flush all traces of the currently running executable */
849 retval = flush_old_exec(bprm); 727 retval = flush_old_exec(bprm);
850 if (retval) 728 if (retval)
@@ -1022,24 +900,19 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1022 } 900 }
1023 901
1024 if (elf_interpreter) { 902 if (elf_interpreter) {
1025 if (IS_AOUT_INTERP(interpreter_type)) { 903 unsigned long uninitialized_var(interp_map_addr);
1026 elf_entry = load_aout_interp(&loc->interp_ex, 904
1027 interpreter); 905 elf_entry = load_elf_interp(&loc->interp_elf_ex,
1028 } else { 906 interpreter,
1029 unsigned long uninitialized_var(interp_map_addr); 907 &interp_map_addr,
1030 908 load_bias);
1031 elf_entry = load_elf_interp(&loc->interp_elf_ex, 909 if (!IS_ERR((void *)elf_entry)) {
1032 interpreter, 910 /*
1033 &interp_map_addr, 911 * load_elf_interp() returns relocation
1034 load_bias); 912 * adjustment
1035 if (!IS_ERR((void *)elf_entry)) { 913 */
1036 /* 914 interp_load_addr = elf_entry;
1037 * load_elf_interp() returns relocation 915 elf_entry += loc->interp_elf_ex.e_entry;
1038 * adjustment
1039 */
1040 interp_load_addr = elf_entry;
1041 elf_entry += loc->interp_elf_ex.e_entry;
1042 }
1043 } 916 }
1044 if (BAD_ADDR(elf_entry)) { 917 if (BAD_ADDR(elf_entry)) {
1045 force_sig(SIGSEGV, current); 918 force_sig(SIGSEGV, current);
@@ -1063,8 +936,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1063 936
1064 kfree(elf_phdata); 937 kfree(elf_phdata);
1065 938
1066 if (!IS_AOUT_INTERP(interpreter_type)) 939 sys_close(elf_exec_fileno);
1067 sys_close(elf_exec_fileno);
1068 940
1069 set_binfmt(&elf_format); 941 set_binfmt(&elf_format);
1070 942
@@ -1079,15 +951,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1079 compute_creds(bprm); 951 compute_creds(bprm);
1080 current->flags &= ~PF_FORKNOEXEC; 952 current->flags &= ~PF_FORKNOEXEC;
1081 retval = create_elf_tables(bprm, &loc->elf_ex, 953 retval = create_elf_tables(bprm, &loc->elf_ex,
1082 IS_AOUT_INTERP(interpreter_type),
1083 load_addr, interp_load_addr); 954 load_addr, interp_load_addr);
1084 if (retval < 0) { 955 if (retval < 0) {
1085 send_sig(SIGKILL, current, 0); 956 send_sig(SIGKILL, current, 0);
1086 goto out; 957 goto out;
1087 } 958 }
1088 /* N.B. passed_fileno might not be initialized? */ 959 /* N.B. passed_fileno might not be initialized? */
1089 if (IS_AOUT_INTERP(interpreter_type))
1090 current->mm->arg_start += strlen(passed_fileno) + 1;
1091 current->mm->end_code = end_code; 960 current->mm->end_code = end_code;
1092 current->mm->start_code = start_code; 961 current->mm->start_code = start_code;
1093 current->mm->start_data = start_data; 962 current->mm->start_data = start_data;