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 4628c42ca89..41a958a7585 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -134,8 +134,7 @@ static int padzero(unsigned long elf_bss) static int create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, - int interp_aout, unsigned long load_addr, - unsigned long interp_load_addr) + unsigned long load_addr, unsigned long interp_load_addr) { unsigned long p = bprm->p; int argc = bprm->argc; @@ -223,12 +222,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, sp = STACK_ADD(p, ei_index); - items = (argc + 1) + (envc + 1); - if (interp_aout) { - items += 3; /* a.out interpreters require argv & envp too */ - } else { - items += 1; /* ELF interpreters only put argc on the stack */ - } + items = (argc + 1) + (envc + 1) + 1; bprm->p = STACK_ROUND(sp, items); /* Point sp at the lowest address on the stack */ @@ -251,16 +245,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, /* Now, let's put argc (and argv, envp if appropriate) on the stack */ if (__put_user(argc, sp++)) return -EFAULT; - if (interp_aout) { - argv = sp + 2; - envp = argv + argc + 1; - if (__put_user((elf_addr_t)(unsigned long)argv, sp++) || - __put_user((elf_addr_t)(unsigned long)envp, sp++)) - return -EFAULT; - } else { - argv = sp; - envp = argv + argc + 1; - } + argv = sp; + envp = argv + argc + 1; /* Populate argv and envp */ p = current->mm->arg_end = current->mm->arg_start; @@ -513,59 +499,12 @@ out: return error; } -static unsigned long load_aout_interp(struct exec *interp_ex, - struct file *interpreter) -{ - unsigned long text_data, elf_entry = ~0UL; - char __user * addr; - loff_t offset; - - current->mm->end_code = interp_ex->a_text; - text_data = interp_ex->a_text + interp_ex->a_data; - current->mm->end_data = text_data; - current->mm->brk = interp_ex->a_bss + text_data; - - switch (N_MAGIC(*interp_ex)) { - case OMAGIC: - offset = 32; - addr = (char __user *)0; - break; - case ZMAGIC: - case QMAGIC: - offset = N_TXTOFF(*interp_ex); - addr = (char __user *)N_TXTADDR(*interp_ex); - break; - default: - goto out; - } - - down_write(¤t->mm->mmap_sem); - do_brk(0, text_data); - up_write(¤t->mm->mmap_sem); - if (!interpreter->f_op || !interpreter->f_op->read) - goto out; - if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) - goto out; - flush_icache_range((unsigned long)addr, - (unsigned long)addr + text_data); - - down_write(¤t->mm->mmap_sem); - do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), - interp_ex->a_bss); - up_write(¤t->mm->mmap_sem); - elf_entry = interp_ex->a_entry; - -out: - return elf_entry; -} - /* * These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. */ #define INTERPRETER_NONE 0 -#define INTERPRETER_AOUT 1 #define INTERPRETER_ELF 2 #ifndef STACK_RND_MASK @@ -594,7 +533,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; char * elf_interpreter = NULL; - unsigned int interpreter_type = INTERPRETER_NONE; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata; unsigned long elf_bss, elf_brk; @@ -605,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; unsigned long reloc_func_desc = 0; - char passed_fileno[6]; struct files_struct *files; int executable_stack = EXSTACK_DEFAULT; unsigned long def_flags = 0; @@ -774,59 +711,18 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { - static int warn; - interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; - - /* Now figure out which format our binary is */ - if ((N_MAGIC(loc->interp_ex) != OMAGIC) && - (N_MAGIC(loc->interp_ex) != ZMAGIC) && - (N_MAGIC(loc->interp_ex) != QMAGIC)) - interpreter_type = INTERPRETER_ELF; - - if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) - interpreter_type &= ~INTERPRETER_ELF; - - if (interpreter_type == INTERPRETER_AOUT && warn < 10) { - printk(KERN_WARNING "a.out ELF interpreter %s is " - "deprecated and will not be supported " - "after Linux 2.6.25\n", elf_interpreter); - warn++; - } - retval = -ELIBBAD; - if (!interpreter_type) + /* Not an ELF interpreter */ + if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out_free_dentry; - - /* Make sure only one type was selected */ - if ((interpreter_type & INTERPRETER_ELF) && - interpreter_type != INTERPRETER_ELF) { - // FIXME - ratelimit this before re-enabling - // printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n"); - interpreter_type = INTERPRETER_ELF; - } /* Verify the interpreter has a valid arch */ - if ((interpreter_type == INTERPRETER_ELF) && - !elf_check_arch(&loc->interp_elf_ex)) + if (!elf_check_arch(&loc->interp_elf_ex)) goto out_free_dentry; } else { /* Executables without an interpreter also need a personality */ SET_PERSONALITY(loc->elf_ex, 0); } - /* OK, we are done with that, now set up the arg stuff, - and then start this sucker up */ - if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { - char *passed_p = passed_fileno; - sprintf(passed_fileno, "%d", elf_exec_fileno); - - if (elf_interpreter) { - retval = copy_strings_kernel(1, &passed_p, bprm); - if (retval) - goto out_free_dentry; - bprm->argc++; - } - } - /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) @@ -1004,24 +900,19 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) } if (elf_interpreter) { - if (interpreter_type == INTERPRETER_AOUT) { - elf_entry = load_aout_interp(&loc->interp_ex, - interpreter); - } else { - unsigned long uninitialized_var(interp_map_addr); - - elf_entry = load_elf_interp(&loc->interp_elf_ex, - interpreter, - &interp_map_addr, - load_bias); - if (!IS_ERR((void *)elf_entry)) { - /* - * load_elf_interp() returns relocation - * adjustment - */ - interp_load_addr = elf_entry; - elf_entry += loc->interp_elf_ex.e_entry; - } + unsigned long uninitialized_var(interp_map_addr); + + elf_entry = load_elf_interp(&loc->interp_elf_ex, + interpreter, + &interp_map_addr, + load_bias); + if (!IS_ERR((void *)elf_entry)) { + /* + * load_elf_interp() returns relocation + * adjustment + */ + interp_load_addr = elf_entry; + elf_entry += loc->interp_elf_ex.e_entry; } if (BAD_ADDR(elf_entry)) { force_sig(SIGSEGV, current); @@ -1045,8 +936,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) kfree(elf_phdata); - if (interpreter_type != INTERPRETER_AOUT) - sys_close(elf_exec_fileno); + sys_close(elf_exec_fileno); set_binfmt(&elf_format); @@ -1061,15 +951,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; retval = create_elf_tables(bprm, &loc->elf_ex, - (interpreter_type == INTERPRETER_AOUT), load_addr, interp_load_addr); if (retval < 0) { send_sig(SIGKILL, current, 0); goto out; } /* N.B. passed_fileno might not be initialized? */ - if (interpreter_type == INTERPRETER_AOUT) - current->mm->arg_start += strlen(passed_fileno) + 1; current->mm->end_code = end_code; current->mm->start_code = start_code; current->mm->start_data = start_data; @@ -1077,7 +964,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) current->mm->start_stack = bprm->p; #ifdef arch_randomize_brk - if (current->flags & PF_RANDOMIZE) + if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) current->mm->brk = current->mm->start_brk = arch_randomize_brk(current->mm); #endif |