| Kernel v2.4.13-ac8 /fs/binfmt_elf.c |
|---|
 2.4.13-ac8
 fs
 binfmt_elf.c
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/binfmt_elf.c linux.ac/fs/binfmt_elf.c
--- linux.vanilla/fs/binfmt_elf.c Thu Oct 25 16:26:38 2001
+++ linux.ac/fs/binfmt_elf.c Fri Nov 2 14:31:33 2001
@@ -32,7 +32,7 @@
#include <linux/highuid.h>
#include <linux/smp_lock.h>
#include <linux/compiler.h>
-#include <linux/limits.h>
+#include <linux/highmem.h>
#include <asm/uaccess.h>
#include <asm/param.h>
@@ -609,9 +609,14 @@
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
current->mm->rss = 0;
- setup_arg_pages(bprm); /* XXX: check error */
+ retval = setup_arg_pages(bprm);
+ if (retval < 0) {
+ /* Someone check-me: is this error path enough? */
+ send_sig(SIGKILL, current, 0);
+ return retval;
+ }
+
current->mm->start_stack = bprm->p;
-
/* Now we do a little grungy work by mmaping the ELF image into
the correct location in memory. At this point, we assume that
the image should be loaded at fixed address, not at a variable
@@ -1032,6 +1037,25 @@
elf_fpregset_t fpu; /* NT_PRFPREG */
struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
+ /* first copy the parameters from user space */
+ memset(&psinfo, 0, sizeof(psinfo));
+ {
+ int i, len;
+
+ len = current->mm->arg_end - current->mm->arg_start;
+ if (len >= ELF_PRARGSZ)
+ len = ELF_PRARGSZ-1;
+ copy_from_user(&psinfo.pr_psargs,
+ (const char *)current->mm->arg_start, len);
+ for(i = 0; i < len; i++)
+ if (psinfo.pr_psargs[i] == 0)
+ psinfo.pr_psargs[i] = ' ';
+ psinfo.pr_psargs[len] = 0;
+
+ }
+
+ /* now stop all vm operations */
+ down_write(¤t->mm->mmap_sem);
segs = current->mm->map_count;
#ifdef DEBUG
@@ -1073,7 +1097,6 @@
* Set up the notes in similar form to SVR4 core dumps made
* with info from their /proc.
*/
- memset(&psinfo, 0, sizeof(psinfo));
memset(&prstatus, 0, sizeof(prstatus));
notes[0].name = "CORE";
@@ -1129,23 +1152,6 @@
psinfo.pr_flag = current->flags;
psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
- {
- int i, len;
-
- set_fs(fs);
-
- len = current->mm->arg_end - current->mm->arg_start;
- if (len >= ELF_PRARGSZ)
- len = ELF_PRARGSZ-1;
- copy_from_user(&psinfo.pr_psargs,
- (const char *)current->mm->arg_start, len);
- for(i = 0; i < len; i++)
- if (psinfo.pr_psargs[i] == 0)
- psinfo.pr_psargs[i] = ' ';
- psinfo.pr_psargs[len] = 0;
-
- set_fs(KERNEL_DS);
- }
strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
notes[2].name = "CORE";
@@ -1217,8 +1223,6 @@
if (!writenote(¬es[i], file))
goto end_coredump;
- set_fs(fs);
-
DUMP_SEEK(dataoff);
for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
@@ -1232,22 +1236,24 @@
for (addr = vma->vm_start;
addr < vma->vm_end;
addr += PAGE_SIZE) {
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgd))
- goto nextpage_coredump;
- pmd = pmd_offset(pgd, addr);
- if (pmd_none(*pmd))
- goto nextpage_coredump;
- pte = pte_offset(pmd, addr);
- if (pte_none(*pte)) {
-nextpage_coredump:
+ struct page* page;
+ struct vm_area_struct *vma;
+
+ if (get_user_pages(current, current->mm, addr, 1, 0, 1,
+ &page, &vma) <= 0) {
DUMP_SEEK (file->f_pos + PAGE_SIZE);
} else {
- DUMP_WRITE((void*)addr, PAGE_SIZE);
+ if (page == ZERO_PAGE(addr)) {
+ DUMP_SEEK (file->f_pos + PAGE_SIZE);
+ } else {
+ void *kaddr;
+ flush_cache_page(vma, addr);
+ kaddr = kmap(page);
+ DUMP_WRITE(kaddr, PAGE_SIZE);
+ flush_page_to_ram(page);
+ kunmap(page);
+ }
+ put_page(page);
}
}
}
@@ -1260,6 +1266,7 @@
end_coredump:
set_fs(fs);
+ up_write(¤t->mm->mmap_sem);
return has_dumped;
}
#endif /* USE_ELF_CORE_DUMP */
|