fix asm-x86/{posix_types,unistd}.h
[safe/jmp/linux-2.6] / fs / binfmt_elf.c
index 786ee27..9924581 100644 (file)
@@ -117,7 +117,7 @@ static int padzero(unsigned long elf_bss)
        return 0;
 }
 
-/* Let's use some macros to make this stack manipulation a litle clearer */
+/* Let's use some macros to make this stack manipulation a little clearer */
 #ifdef CONFIG_STACK_GROWSUP
 #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
 #define STACK_ROUND(sp, items) \
@@ -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(&current->mm->mmap_sem);     
-       do_brk(0, text_data);
-       up_write(&current->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(&current->mm->mmap_sem);     
-       do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
-               interp_ex->a_bss);
-       up_write(&current->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,8 +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 char ibcs2_interpreter = 0;
        unsigned long error;
        struct elf_phdr *elf_ppnt, *elf_phdata;
        unsigned long elf_bss, elf_brk;
@@ -606,8 +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;
        struct {
@@ -657,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                goto out_free_ph;
        }
 
-       files = current->files; /* Refcounted so ok */
-       retval = unshare_files();
-       if (retval < 0)
-               goto out_free_ph;
-       if (files == current->files) {
-               put_files_struct(files);
-               files = NULL;
-       }
-
-       /* exec will make our files private anyway, but for the a.out
-          loader stuff we need to do it earlier */
        retval = get_unused_fd();
        if (retval < 0)
-               goto out_free_fh;
+               goto out_free_ph;
        get_file(bprm->file);
        fd_install(elf_exec_fileno = retval, bprm->file);
 
@@ -713,14 +637,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                        if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
                                goto out_free_interp;
 
-                       /* If the program interpreter is one of these two,
-                        * then assume an iBCS2 image. Otherwise assume
-                        * a native linux image.
-                        */
-                       if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-                           strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
-                               ibcs2_interpreter = 1;
-
                        /*
                         * The early SET_PERSONALITY here is so that the lookup
                         * for the interpreter happens in the namespace of the 
@@ -740,7 +656,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         * switch really is going to happen - do this in
                         * flush_thread().      - akpm
                         */
-                       SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
+                       SET_PERSONALITY(loc->elf_ex, 0);
 
                        interpreter = open_exec(elf_interpreter);
                        retval = PTR_ERR(interpreter);
@@ -783,57 +699,16 @@ 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, ibcs2_interpreter);
-       }
-
-       /* 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++;
-               }
+               SET_PERSONALITY(loc->elf_ex, 0);
        }
 
        /* Flush all traces of the currently running executable */
@@ -841,19 +716,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (retval)
                goto out_free_dentry;
 
-       /* Discard our unneeded old files struct */
-       if (files) {
-               put_files_struct(files);
-               files = NULL;
-       }
-
        /* OK, This is the point of no return */
        current->flags &= ~PF_FORKNOEXEC;
        current->mm->def_flags = def_flags;
 
        /* Do this immediately, since STACK_TOP as used in setup_arg_pages
           may depend on the personality.  */
-       SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
+       SET_PERSONALITY(loc->elf_ex, 0);
        if (elf_read_implies_exec(loc->elf_ex, executable_stack))
                current->personality |= READ_IMPLIES_EXEC;
 
@@ -1013,24 +882,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);
@@ -1054,8 +918,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);
 
@@ -1070,15 +933,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;
@@ -1086,7 +946,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
@@ -1138,9 +998,6 @@ out_free_interp:
        kfree(elf_interpreter);
 out_free_file:
        sys_close(elf_exec_fileno);
-out_free_fh:
-       if (files)
-               reset_files_struct(current, files);
 out_free_ph:
        kfree(elf_phdata);
        goto out;
@@ -1546,6 +1403,18 @@ struct elf_note_info {
        int thread_notes;
 };
 
+/*
+ * When a regset has a writeback hook, we call it on each thread before
+ * dumping user memory.  On register window machines, this makes sure the
+ * user memory backing the register data is up to date before we read it.
+ */
+static void do_thread_regset_writeback(struct task_struct *task,
+                                      const struct user_regset *regset)
+{
+       if (regset->writeback)
+               regset->writeback(task, regset, 1);
+}
+
 static int fill_thread_core_info(struct elf_thread_core_info *t,
                                 const struct user_regset_view *view,
                                 long signr, size_t *total)
@@ -1567,6 +1436,8 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
                  sizeof(t->prstatus), &t->prstatus);
        *total += notesize(&t->notes[0]);
 
+       do_thread_regset_writeback(t->task, &view->regsets[0]);
+
        /*
         * Each other regset might generate a note too.  For each regset
         * that has no core_note_type or is inactive, we leave t->notes[i]
@@ -1574,6 +1445,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
         */
        for (i = 1; i < view->n; ++i) {
                const struct user_regset *regset = &view->regsets[i];
+               do_thread_regset_writeback(t->task, regset);
                if (regset->core_note_type &&
                    (!regset->active || regset->active(t->task, regset))) {
                        int ret;