|
@@ -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,61 +499,6 @@ out:
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_ARCH_SUPPORTS_AOUT
|
|
|
-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;
|
|
|
-}
|
|
|
-#else
|
|
|
-/* dummy extern - the function should never be called if !CONFIG_AOUT_BINFMT */
|
|
|
-static inline unsigned long load_aout_interp(struct exec *interp_ex,
|
|
|
- struct file *interpreter)
|
|
|
-{
|
|
|
- return -ELIBACC;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* These are the functions used to load ELF style executables and shared
|
|
|
* libraries. There is no binary dependent code anywhere else.
|
|
@@ -576,13 +507,6 @@ static inline unsigned long load_aout_interp(struct exec *interp_ex,
|
|
|
#define INTERPRETER_NONE 0
|
|
|
#define INTERPRETER_ELF 2
|
|
|
|
|
|
-#ifdef CONFIG_ARCH_SUPPORTS_AOUT
|
|
|
-#define INTERPRETER_AOUT 1
|
|
|
-#define IS_AOUT_INTERP(x) ((x) == INTERPRETER_AOUT)
|
|
|
-#else
|
|
|
-#define IS_AOUT_INTERP(x) (0)
|
|
|
-#endif
|
|
|
-
|
|
|
#ifndef STACK_RND_MASK
|
|
|
#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */
|
|
|
#endif
|
|
@@ -609,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;
|
|
@@ -620,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;
|
|
@@ -789,62 +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;
|
|
|
-#ifdef CONFIG_ARCH_SUPPORTS_AOUT
|
|
|
- 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;
|
|
|
-#else
|
|
|
- interpreter_type = INTERPRETER_ELF;
|
|
|
-#endif
|
|
|
- if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
|
|
|
- interpreter_type &= ~INTERPRETER_ELF;
|
|
|
-
|
|
|
- if (IS_AOUT_INTERP(interpreter_type) && 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 (IS_AOUT_INTERP(interpreter_type) && !bprm->sh_bang) {
|
|
|
- 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)
|
|
@@ -1022,24 +900,19 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
|
|
}
|
|
|
|
|
|
if (elf_interpreter) {
|
|
|
- if (IS_AOUT_INTERP(interpreter_type)) {
|
|
|
- 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);
|
|
@@ -1063,8 +936,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
|
|
|
|
|
kfree(elf_phdata);
|
|
|
|
|
|
- if (!IS_AOUT_INTERP(interpreter_type))
|
|
|
- sys_close(elf_exec_fileno);
|
|
|
+ sys_close(elf_exec_fileno);
|
|
|
|
|
|
set_binfmt(&elf_format);
|
|
|
|
|
@@ -1079,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,
|
|
|
- IS_AOUT_INTERP(interpreter_type),
|
|
|
load_addr, interp_load_addr);
|
|
|
if (retval < 0) {
|
|
|
send_sig(SIGKILL, current, 0);
|
|
|
goto out;
|
|
|
}
|
|
|
/* N.B. passed_fileno might not be initialized? */
|
|
|
- if (IS_AOUT_INTERP(interpreter_type))
|
|
|
- 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;
|