VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / binfmt_elf.c
index a67e6f5..785da46 100644 (file)
 #include <linux/pagemap.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/vs_memory.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
-#include <asm/pgalloc.h>
 
 #include <linux/elf.h>
 
@@ -110,18 +110,18 @@ static void padzero(unsigned long elf_bss)
        nbyte = ELF_PAGEOFFSET(elf_bss);
        if (nbyte) {
                nbyte = ELF_MIN_ALIGN - nbyte;
-               clear_user((void *) elf_bss, nbyte);
+               clear_user((void __user *) elf_bss, nbyte);
        }
 }
 
 /* Let's use some macros to make this stack manipulation a litle clearer */
 #ifdef CONFIG_STACK_GROWSUP
-#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) + (items))
+#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
 #define STACK_ROUND(sp, items) \
        ((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
-#define STACK_ALLOC(sp, len) ({ elf_addr_t *old_sp = (elf_addr_t *)sp; sp += len; old_sp; })
+#define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; })
 #else
-#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) - (items))
+#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))
 #define STACK_ROUND(sp, items) \
        (((unsigned long) (sp - items)) &~ 15UL)
 #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
@@ -135,8 +135,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        unsigned long p = bprm->p;
        int argc = bprm->argc;
        int envc = bprm->envc;
-       elf_addr_t *argv, *envp;
-       elf_addr_t *sp, *u_platform;
+       elf_addr_t __user *argv;
+       elf_addr_t __user *envp;
+       elf_addr_t __user *sp;
+       elf_addr_t __user *u_platform;
        const char *k_platform = ELF_PLATFORM;
        int items;
        elf_addr_t *elf_info;
@@ -169,7 +171,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
                if (smp_num_siblings > 1)
                        STACK_ALLOC(p, ((current->pid % 64) << 7));
 #endif
-               u_platform = (elf_addr_t *)STACK_ALLOC(p, len);
+               u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
                __copy_to_user(u_platform, k_platform, len);
        }
 
@@ -200,7 +202,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid);
        NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));
        if (k_platform) {
-               NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(long)u_platform);
+               NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);
+       }
+       if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
+               NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data);
        }
 #undef NEW_AUX_ENT
        /* AT_NULL is zero; clear the rest too */
@@ -222,10 +227,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
 
        /* Point sp at the lowest address on the stack */
 #ifdef CONFIG_STACK_GROWSUP
-       sp = (elf_addr_t *)bprm->p - items - ei_index;
+       sp = (elf_addr_t __user *)bprm->p - items - ei_index;
        bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */
 #else
-       sp = (elf_addr_t *)bprm->p;
+       sp = (elf_addr_t __user *)bprm->p;
 #endif
 
        /* Now, let's put argc (and argv, envp if appropriate) on the stack */
@@ -233,8 +238,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        if (interp_aout) {
                argv = sp + 2;
                envp = argv + argc + 1;
-               __put_user((elf_addr_t)(long)argv, sp++);
-               __put_user((elf_addr_t)(long)envp, sp++);
+               __put_user((elf_addr_t)(unsigned long)argv, sp++);
+               __put_user((elf_addr_t)(unsigned long)envp, sp++);
        } else {
                argv = sp;
                envp = argv + argc + 1;
@@ -245,7 +250,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        while (argc-- > 0) {
                size_t len;
                __put_user((elf_addr_t)p, argv++);
-               len = strnlen_user((void *)p, PAGE_SIZE*MAX_ARG_PAGES);
+               len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
                        return;
                p += len;
@@ -255,7 +260,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        while (envc-- > 0) {
                size_t len;
                __put_user((elf_addr_t)p, envp++);
-               len = strnlen_user((void *)p, PAGE_SIZE*MAX_ARG_PAGES);
+               len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
                        return;
                p += len;
@@ -264,7 +269,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        current->mm->env_end = p;
 
        /* Put the elf_info on the stack in the right place.  */
-       sp = (elf_addr_t *)envp + 1;
+       sp = (elf_addr_t __user *)envp + 1;
        copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t));
 }
 
@@ -418,7 +423,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
                             struct file * interpreter)
 {
        unsigned long text_data, elf_entry = ~0UL;
-       char * addr;
+       char __user * addr;
        loff_t offset;
 
        current->mm->end_code = interp_ex->a_text;
@@ -429,12 +434,12 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
        switch (N_MAGIC(*interp_ex)) {
        case OMAGIC:
                offset = 32;
-               addr = (char *) 0;
+               addr = (char __user *)0;
                break;
        case ZMAGIC:
        case QMAGIC:
                offset = N_TXTOFF(*interp_ex);
-               addr = (char *) N_TXTADDR(*interp_ex);
+               addr = (char __user *) N_TXTADDR(*interp_ex);
                break;
        default:
                goto out;
@@ -488,7 +493,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        struct exec interp_ex;
        char passed_fileno[6];
        struct files_struct *files;
-       int executable_stack = EXSTACK_DEFAULT;
+       int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
+       unsigned long def_flags = 0;
        
        /* Get the exec-header */
        elf_ex = *((struct elfhdr *) bprm->buf);
@@ -620,7 +626,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                executable_stack = EXSTACK_ENABLE_X;
                        else
                                executable_stack = EXSTACK_DISABLE_X;
+                       break;
                }
+       have_pt_gnu_stack = (i < elf_ex.e_phnum);
 
        /* Some simple consistency checks for the interpreter */
        if (elf_interpreter) {
@@ -688,14 +696,18 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->mm->end_code = 0;
        current->mm->mmap = NULL;
        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(elf_ex, ibcs2_interpreter);
+       if (elf_read_implies_exec(elf_ex, have_pt_gnu_stack))
+               current->personality |= READ_IMPLIES_EXEC;
 
        /* Do this so that we can load the interpreter, if need be.  We will
           change some of these later */
-       current->mm->rss = 0;
+       // current->mm->rss = 0;
+       vx_rsspages_sub(current->mm, current->mm->rss);
        current->mm->free_area_cache = TASK_UNMAPPED_BASE;
        retval = setup_arg_pages(bprm, executable_stack);
        if (retval < 0) {
@@ -734,7 +746,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                nbyte = ELF_MIN_ALIGN - nbyte;
                                if (nbyte > elf_brk - elf_bss)
                                        nbyte = elf_brk - elf_bss;
-                               clear_user((void *) elf_bss + load_bias, nbyte);
+                               clear_user((void __user *) elf_bss + load_bias, nbyte);
                        }
                }
 
@@ -1184,7 +1196,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
        if (len >= ELF_PRARGSZ)
                len = ELF_PRARGSZ-1;
        copy_from_user(&psinfo->pr_psargs,
-                      (const char *)mm->arg_start, len);
+                      (const char __user *)mm->arg_start, len);
        for(i = 0; i < len; i++)
                if (psinfo->pr_psargs[i] == 0)
                        psinfo->pr_psargs[i] = ' ';
@@ -1543,6 +1555,6 @@ static void __exit exit_elf_binfmt(void)
        unregister_binfmt(&elf_format);
 }
 
-module_init(init_elf_binfmt)
-module_exit(exit_elf_binfmt)
+core_initcall(init_elf_binfmt);
+module_exit(exit_elf_binfmt);
 MODULE_LICENSE("GPL");