This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / binfmt_elf.c
index cb0db6e..3c89c56 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/pagemap.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/random.h>
 #include <linux/vs_memory.h>
 
 #include <asm/uaccess.h>
@@ -70,6 +71,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file);
 # define ELF_MIN_ALIGN PAGE_SIZE
 #endif
 
+#ifndef ELF_CORE_EFLAGS
+#define ELF_CORE_EFLAGS        0
+#endif
+
 #define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
 #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))
 #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
@@ -89,7 +94,10 @@ static int set_brk(unsigned long start, unsigned long end)
        start = ELF_PAGEALIGN(start);
        end = ELF_PAGEALIGN(end);
        if (end > start) {
-               unsigned long addr = do_brk(start, end - start);
+               unsigned long addr;
+               down_write(&current->mm->mmap_sem);
+               addr = do_brk(start, end - start);
+               up_write(&current->mm->mmap_sem);
                if (BAD_ADDR(addr))
                        return addr;
        }
@@ -104,15 +112,17 @@ static int set_brk(unsigned long start, unsigned long end)
    be in memory */
 
 
-static void padzero(unsigned long elf_bss)
+static int padzero(unsigned long elf_bss)
 {
        unsigned long nbyte;
 
        nbyte = ELF_PAGEOFFSET(elf_bss);
        if (nbyte) {
                nbyte = ELF_MIN_ALIGN - nbyte;
-               clear_user((void __user *) elf_bss, nbyte);
+               if (clear_user((void __user *) elf_bss, nbyte))
+                       return -EFAULT;
        }
+       return 0;
 }
 
 /* Let's use some macros to make this stack manipulation a litle clearer */
@@ -128,7 +138,7 @@ static void padzero(unsigned long elf_bss)
 #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
 #endif
 
-static void
+static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
                int interp_aout, unsigned long load_addr,
                unsigned long interp_load_addr)
@@ -157,23 +167,17 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        if (k_platform) {
                size_t len = strlen(k_platform) + 1;
 
-#ifdef CONFIG_X86_HT
                /*
                 * In some cases (e.g. Hyper-Threading), we want to avoid L1
                 * evictions by the processes running on the same package. One
                 * thing we can do is to shuffle the initial stack for them.
-                *
-                * The conditionals here are unneeded, but kept in to make the
-                * code behaviour the same as pre change unless we have
-                * hyperthreaded processors. This should be cleaned up
-                * before 2.6
                 */
         
-               if (smp_num_siblings > 1)
-                       STACK_ALLOC(p, ((current->pid % 64) << 7));
-#endif
+               p = arch_align_stack(p);
+
                u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
-               __copy_to_user(u_platform, k_platform, len);
+               if (__copy_to_user(u_platform, k_platform, len))
+                       return -EFAULT;
        }
 
        /* Create the ELF interpreter info */
@@ -235,7 +239,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
 #endif
 
        /* Now, let's put argc (and argv, envp if appropriate) on the stack */
-       __put_user(argc, sp++);
+       if (__put_user(argc, sp++))
+               return -EFAULT;
        if (interp_aout) {
                argv = sp + 2;
                envp = argv + argc + 1;
@@ -247,31 +252,35 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
        }
 
        /* Populate argv and envp */
-       p = current->mm->arg_start;
+       p = current->mm->arg_end = current->mm->arg_start;
        while (argc-- > 0) {
                size_t len;
                __put_user((elf_addr_t)p, argv++);
                len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
-                       return;
+                       return 0;
                p += len;
        }
-       __put_user(0, argv);
+       if (__put_user(0, argv))
+               return -EFAULT;
        current->mm->arg_end = current->mm->env_start = p;
        while (envc-- > 0) {
                size_t len;
                __put_user((elf_addr_t)p, envp++);
                len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);
                if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
-                       return;
+                       return 0;
                p += len;
        }
-       __put_user(0, envp);
+       if (__put_user(0, envp))
+               return -EFAULT;
        current->mm->env_end = p;
 
        /* Put the elf_info on the stack in the right place.  */
        sp = (elf_addr_t __user *)envp + 1;
-       copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t));
+       if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t)))
+               return -EFAULT;
+       return 0;
 }
 
 #ifndef elf_map
@@ -323,7 +332,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
         */
        if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
                goto out;
-       if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
+       if (interp_elf_ex->e_phnum < 1 ||
+               interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
                goto out;
 
        /* Now read in all of the header information */
@@ -336,9 +346,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
                goto out;
 
        retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
-       error = retval;
-       if (retval < 0)
+       error = -EIO;
+       if (retval != size) {
+               if (retval < 0)
+                       error = retval; 
                goto out_close;
+       }
 
        eppnt = elf_phdata;
        for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
@@ -401,12 +414,18 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
         * that there are zero-mapped pages up to and including the 
         * last bss page.
         */
-       padzero(elf_bss);
+       if (padzero(elf_bss)) {
+               error = -EFAULT;
+               goto out_close;
+       }
+
        elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);   /* What we have mapped so far */
 
        /* Map the last of the bss segment */
        if (last_bss > elf_bss) {
+               down_write(&current->mm->mmap_sem);
                error = do_brk(elf_bss, last_bss - elf_bss);
+               up_write(&current->mm->mmap_sem);
                if (BAD_ADDR(error))
                        goto out_close;
        }
@@ -446,7 +465,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
                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)
@@ -454,8 +475,11 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
        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:
@@ -472,6 +496,19 @@ out:
 #define INTERPRETER_ELF 2
 
 
+static unsigned long randomize_stack_top(unsigned long stack_top)
+{
+       unsigned int random_variable = 0;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_variable = get_random_int() % (8*1024*1024);
+#ifdef CONFIG_STACK_GROWSUP
+       return PAGE_ALIGN(stack_top + random_variable);
+#else
+       return PAGE_ALIGN(stack_top - random_variable);
+#endif
+}
+
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
        struct file *interpreter = NULL; /* to shut gcc up */
@@ -522,19 +559,23 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
        /* Now read in all of the header information */
 
-       retval = -ENOMEM;
        if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
                goto out;
-       if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
+       if (loc->elf_ex.e_phnum < 1 ||
+               loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
                goto out;
        size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
+       retval = -ENOMEM;
        elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
        if (!elf_phdata)
                goto out;
 
        retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
-       if (retval < 0)
+       if (retval != size) {
+               if (retval >= 0)
+                       retval = -EIO;
                goto out_free_ph;
+       }
 
        files = current->files;         /* Refcounted so ok */
        retval = unshare_files();
@@ -570,9 +611,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                         * is an a.out format binary
                         */
 
-                       retval = -ENOMEM;
-                       if (elf_ppnt->p_filesz > PATH_MAX)
+                       retval = -ENOEXEC;
+                       if (elf_ppnt->p_filesz > PATH_MAX || 
+                           elf_ppnt->p_filesz < 2)
                                goto out_free_file;
+
+                       retval = -ENOMEM;
                        elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
                                                           GFP_KERNEL);
                        if (!elf_interpreter)
@@ -581,8 +625,16 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        retval = kernel_read(bprm->file, elf_ppnt->p_offset,
                                           elf_interpreter,
                                           elf_ppnt->p_filesz);
-                       if (retval < 0)
+                       if (retval != elf_ppnt->p_filesz) {
+                               if (retval >= 0)
+                                       retval = -EIO;
+                               goto out_free_interp;
+                       }
+                       /* make sure path is NULL terminated */
+                       retval = -ENOEXEC;
+                       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.
@@ -617,8 +669,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        if (IS_ERR(interpreter))
                                goto out_free_interp;
                        retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
-                       if (retval < 0)
+                       if (retval != BINPRM_BUF_SIZE) {
+                               if (retval >= 0)
+                                       retval = -EIO;
                                goto out_free_dentry;
+                       }
 
                        /* Get the exec headers */
                        loc->interp_ex = *((struct exec *) bprm->buf);
@@ -710,17 +765,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        /* Do this immediately, since STACK_TOP as used in setup_arg_pages
           may depend on the personality.  */
        SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
-       if (elf_read_implies_exec(loc->elf_ex, have_pt_gnu_stack))
+       if (elf_read_implies_exec(loc->elf_ex, executable_stack))
                current->personality |= READ_IMPLIES_EXEC;
 
+       if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+               current->flags |= PF_RANDOMIZE;
        arch_pick_mmap_layout(current->mm);
 
        /* Do this so that we can load the interpreter, if need be.  We will
           change some of these later */
-       // current->mm->rss = 0;
-       vx_rsspages_sub(current->mm, current->mm->rss);
+       set_mm_counter(current->mm, rss, 0);
        current->mm->free_area_cache = current->mm->mmap_base;
-       retval = setup_arg_pages(bprm, executable_stack);
+       retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
+                                executable_stack);
        if (retval < 0) {
                send_sig(SIGKILL, current, 0);
                goto out_free_dentry;
@@ -757,7 +814,14 @@ 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 __user *) elf_bss + load_bias, nbyte);
+                               if (clear_user((void __user *)elf_bss +
+                                                       load_bias, nbyte)) {
+                                       /*
+                                        * This bss-zeroing can fail if the ELF
+                                        * file specifies odd protections.  So
+                                        * we don't check the return value
+                                        */
+                               }
                        }
                }
 
@@ -778,8 +842,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
-               if (BAD_ADDR(error))
-                       continue;
+               if (BAD_ADDR(error)) {
+                       send_sig(SIGKILL, current, 0);
+                       goto out_free_dentry;
+               }
 
                if (!load_addr_set) {
                        load_addr_set = 1;
@@ -839,7 +905,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                send_sig(SIGKILL, current, 0);
                goto out_free_dentry;
        }
-       padzero(elf_bss);
+       if (padzero(elf_bss)) {
+               send_sig(SIGSEGV, current, 0);
+               retval = -EFAULT; /* Nobody gets to see this, but.. */
+               goto out_free_dentry;
+       }
 
        if (elf_interpreter) {
                if (interpreter_type == INTERPRETER_AOUT)
@@ -850,8 +920,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                                    interpreter,
                                                    &interp_load_addr);
                if (BAD_ADDR(elf_entry)) {
-                       printk(KERN_ERR "Unable to load interpreter\n");
-                       send_sig(SIGSEGV, current, 0);
+                       printk(KERN_ERR "Unable to load interpreter %.128s\n",
+                               elf_interpreter);
+                       force_sig(SIGSEGV, current);
                        retval = -ENOEXEC; /* Nobody gets to see this, but.. */
                        goto out_free_dentry;
                }
@@ -871,6 +942,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
        set_binfmt(&elf_format);
 
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+       retval = arch_setup_additional_pages(bprm, executable_stack);
+       if (retval < 0) {
+               send_sig(SIGKILL, current, 0);
+               goto out;
+       }
+#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
        compute_creds(bprm);
        current->flags &= ~PF_FORKNOEXEC;
        create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
@@ -948,6 +1027,7 @@ out_free_ph:
 static int load_elf_library(struct file *file)
 {
        struct elf_phdr *elf_phdata;
+       struct elf_phdr *eppnt;
        unsigned long elf_bss, bss, len;
        int retval, error, i, j;
        struct elfhdr elf_ex;
@@ -971,43 +1051,52 @@ static int load_elf_library(struct file *file)
        /* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */
 
        error = -ENOMEM;
-       elf_phdata = (struct elf_phdr *) kmalloc(j, GFP_KERNEL);
+       elf_phdata = kmalloc(j, GFP_KERNEL);
        if (!elf_phdata)
                goto out;
 
+       eppnt = elf_phdata;
        error = -ENOEXEC;
-       retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, j);
+       retval = kernel_read(file, elf_ex.e_phoff, (char *)eppnt, j);
        if (retval != j)
                goto out_free_ph;
 
        for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
-               if ((elf_phdata + i)->p_type == PT_LOAD) j++;
+               if ((eppnt + i)->p_type == PT_LOAD)
+                       j++;
        if (j != 1)
                goto out_free_ph;
 
-       while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
+       while (eppnt->p_type != PT_LOAD)
+               eppnt++;
 
        /* Now use mmap to map the library into memory. */
        down_write(&current->mm->mmap_sem);
        error = do_mmap(file,
-                       ELF_PAGESTART(elf_phdata->p_vaddr),
-                       (elf_phdata->p_filesz +
-                        ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
+                       ELF_PAGESTART(eppnt->p_vaddr),
+                       (eppnt->p_filesz +
+                        ELF_PAGEOFFSET(eppnt->p_vaddr)),
                        PROT_READ | PROT_WRITE | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
-                       (elf_phdata->p_offset -
-                        ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
+                       (eppnt->p_offset -
+                        ELF_PAGEOFFSET(eppnt->p_vaddr)));
        up_write(&current->mm->mmap_sem);
-       if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
+       if (error != ELF_PAGESTART(eppnt->p_vaddr))
                goto out_free_ph;
 
-       elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz;
-       padzero(elf_bss);
+       elf_bss = eppnt->p_vaddr + eppnt->p_filesz;
+       if (padzero(elf_bss)) {
+               error = -EFAULT;
+               goto out_free_ph;
+       }
 
-       len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);
-       bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
-       if (bss > len)
+       len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1);
+       bss = eppnt->p_memsz + eppnt->p_vaddr;
+       if (bss > len) {
+               down_write(&current->mm->mmap_sem);
                do_brk(len, bss - len);
+               up_write(&current->mm->mmap_sem);
+       }
        error = 0;
 
 out_free_ph:
@@ -1037,7 +1126,7 @@ static int dump_write(struct file *file, const void *addr, int nr)
        return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
 }
 
-static int dump_seek(struct file *file, off_t off)
+static int dump_seek(struct file *file, loff_t off)
 {
        if (file->f_op->llseek) {
                if (file->f_op->llseek(file, off, 0) != off)
@@ -1056,22 +1145,18 @@ static int dump_seek(struct file *file, off_t off)
  */
 static int maydump(struct vm_area_struct *vma)
 {
-       /*
-        * If we may not read the contents, don't allow us to dump
-        * them either. "dump_write()" can't handle it anyway.
-        */
-       if (!(vma->vm_flags & VM_READ))
+       /* Do not dump I/O mapped devices or special mappings */
+       if (vma->vm_flags & (VM_IO | VM_RESERVED))
                return 0;
 
-       /* Do not dump I/O mapped devices! -DaveM */
-       if (vma->vm_flags & VM_IO)
-               return 0;
-#if 1
-       if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
-               return 1;
-       if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
+       /* Dump shared memory only if mapped from an anonymous file.  */
+       if (vma->vm_flags & VM_SHARED)
+               return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
+
+       /* If it hasn't been written to, don't write it out */
+       if (!vma->anon_vma)
                return 0;
-#endif
+
        return 1;
 }
 
@@ -1144,7 +1229,7 @@ static inline void fill_elf_header(struct elfhdr *elf, int segs)
        elf->e_entry = 0;
        elf->e_phoff = sizeof(struct elfhdr);
        elf->e_shoff = 0;
-       elf->e_flags = 0;
+       elf->e_flags = ELF_CORE_EFLAGS;
        elf->e_ehsize = sizeof(struct elfhdr);
        elf->e_phentsize = sizeof(struct elf_phdr);
        elf->e_phnum = segs;
@@ -1191,7 +1276,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
        prstatus->pr_ppid = p->parent->pid;
        prstatus->pr_pgrp = process_group(p);
        prstatus->pr_sid = p->signal->session;
-       if (p->pid == p->tgid) {
+       if (thread_group_leader(p)) {
                /*
                 * This is the record for the group leader.  Add in the
                 * cumulative times of previous dead threads.  This total
@@ -1202,22 +1287,22 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
                 * this and each other thread to finish dying after the
                 * core dump synchronization phase.
                 */
-               jiffies_to_timeval(p->utime + p->signal->utime,
+               cputime_to_timeval(cputime_add(p->utime, p->signal->utime),
                                   &prstatus->pr_utime);
-               jiffies_to_timeval(p->stime + p->signal->stime,
+               cputime_to_timeval(cputime_add(p->stime, p->signal->stime),
                                   &prstatus->pr_stime);
        } else {
-               jiffies_to_timeval(p->utime, &prstatus->pr_utime);
-               jiffies_to_timeval(p->stime, &prstatus->pr_stime);
+               cputime_to_timeval(p->utime, &prstatus->pr_utime);
+               cputime_to_timeval(p->stime, &prstatus->pr_stime);
        }
-       jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
-       jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
+       cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
+       cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
 }
 
-static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
-                       struct mm_struct *mm)
+static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
+                      struct mm_struct *mm)
 {
-       int i, len;
+       unsigned int i, len;
        
        /* first copy the parameters from user space */
        memset(psinfo, 0, sizeof(struct elf_prpsinfo));
@@ -1225,8 +1310,9 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
        len = mm->arg_end - mm->arg_start;
        if (len >= ELF_PRARGSZ)
                len = ELF_PRARGSZ-1;
-       copy_from_user(&psinfo->pr_psargs,
-                      (const char __user *)mm->arg_start, len);
+       if (copy_from_user(&psinfo->pr_psargs,
+                          (const char __user *)mm->arg_start, len))
+               return -EFAULT;
        for(i = 0; i < len; i++)
                if (psinfo->pr_psargs[i] == 0)
                        psinfo->pr_psargs[i] = ' ';
@@ -1247,7 +1333,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
        SET_GID(psinfo->pr_gid, p->gid);
        strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
        
-       return;
+       return 0;
 }
 
 /* Here is the structure in which status of each thread is captured. */
@@ -1316,7 +1402,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
        struct vm_area_struct *vma;
        struct elfhdr *elf = NULL;
        off_t offset = 0, dataoff;
-       unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
+       unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
        int numnote;
        struct memelfnote *notes = NULL;
        struct elf_prstatus *prstatus = NULL;   /* NT_PRSTATUS */
@@ -1526,7 +1612,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
                                        DUMP_SEEK (file->f_pos + PAGE_SIZE);
                                } else {
                                        void *kaddr;
-                                       flush_cache_page(vma, addr);
+                                       flush_cache_page(vma, addr, page_to_pfn(page));
                                        kaddr = kmap(page);
                                        if ((size += PAGE_SIZE) > limit ||
                                            !dump_write(file, kaddr,