diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-28 01:09:25 +0000 |
commit | b9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch) | |
tree | 42d07b0c7246ae2536a702e7c5de9e2732341116 /fs/binfmt_elf.c | |
parent | 7406b0a326f2d70ade2671c37d1beef62249db97 (diff) |
Merge with 2.3.99-pre6.
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 87 |
1 files changed, 44 insertions, 43 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index a12183834..788d8c0d5 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -487,10 +487,22 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) #ifdef __sparc__ if (ibcs2_interpreter) { unsigned long old_pers = current->personality; - - current->personality = PER_SVR4; + struct exec_domain *old_domain = current->exec_domain; + struct exec_domain *new_domain; + struct fs_struct *old_fs = current->fs, *new_fs; + get_exec_domain(old_domain); + atomic_inc(&old_fs->count); + + set_personality(PER_SVR4); interpreter = open_exec(elf_interpreter); + + new_domain = current->exec_domain; + new_fs = current->fs; current->personality = old_pers; + current->exec_domain = old_domain; + current->fs = old_fs; + put_exec_domain(new_domain); + put_fs_struct(new_fs); } else #endif { @@ -676,19 +688,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); - put_exec_domain(current->exec_domain); - if (current->binfmt && current->binfmt->module) - __MOD_DEC_USE_COUNT(current->binfmt->module); - current->exec_domain = lookup_exec_domain(current->personality); - current->binfmt = &elf_format; - if (current->binfmt && current->binfmt->module) - __MOD_INC_USE_COUNT(current->binfmt->module); + set_binfmt(&elf_format); -#ifndef VM_STACK_FLAGS - lock_kernel(); - current->executable = dget(bprm->file->f_dentry); - unlock_kernel(); -#endif compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) @@ -970,7 +971,7 @@ static int writenote(struct memelfnote *men, struct file *file) #undef DUMP_SEEK #define DUMP_WRITE(addr, nr) \ - if (!dump_write(file, (addr), (nr))) \ + if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ goto end_coredump; #define DUMP_SEEK(off) \ if (!dump_seek(file, (off))) \ @@ -987,8 +988,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) int has_dumped = 0; mm_segment_t fs; int segs; + size_t size = 0; int i; - size_t size; struct vm_area_struct *vma; struct elfhdr elf; off_t offset = 0, dataoff; @@ -999,24 +1000,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - /* Count what's needed to dump, up to the limit of coredump size */ - segs = 0; - size = 0; - for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { - if (maydump(vma)) - { - unsigned long sz = vma->vm_end-vma->vm_start; - - if (size+sz >= limit) - break; - else - size += sz; - } + segs = current->mm->map_count; - segs++; - } #ifdef DEBUG - printk("elf_core_dump: %d segs taking %d bytes\n", segs, size); + printk("elf_core_dump: %d segs %lu limit\n", segs, limit); #endif /* Set up header */ @@ -1173,13 +1160,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* Write program headers for segments dump */ - for(vma = current->mm->mmap, i = 0; - i < segs && vma != NULL; vma = vma->vm_next) { + for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { struct elf_phdr phdr; size_t sz; - i++; - sz = vma->vm_end - vma->vm_start; phdr.p_type = PT_LOAD; @@ -1205,19 +1189,36 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) DUMP_SEEK(dataoff); - for(i = 0, vma = current->mm->mmap; - i < segs && vma != NULL; - vma = vma->vm_next) { - unsigned long addr = vma->vm_start; - unsigned long len = vma->vm_end - vma->vm_start; + for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { + unsigned long addr; - i++; if (!maydump(vma)) continue; #ifdef DEBUG printk("elf_core_dump: writing %08lx %lx\n", addr, len); #endif - DUMP_WRITE((void *)addr, len); + 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); + pmd = pmd_alloc(pgd, addr); + + if (!pmd) + goto end_coredump; + pte = pte_alloc(pmd, addr); + if (!pte) + goto end_coredump; + if (!pte_present(*pte) && + pte_none(*pte)) { + DUMP_SEEK (file->f_pos + PAGE_SIZE); + } else { + DUMP_WRITE((void*)addr, PAGE_SIZE); + } + } } if ((off_t) file->f_pos != offset) { |