diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 9e26e9e85576..d21ff89207cd 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -187,7 +187,7 @@ static int aout_core_dump(struct coredump_params *cprm) if (!dump_emit(cprm, &dump, sizeof(dump))) goto end_coredump; /* Now dump all of the user data. Include malloced stuff as well */ - if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump))) + if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump))) goto end_coredump; /* now we start writing out the user space info */ set_fs(USER_DS); diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index a4f847f77234..ca0ba15a7306 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -87,7 +87,7 @@ static int aout_core_dump(struct coredump_params *cprm) if (!dump_emit(cprm, &dump, sizeof(dump))) goto end_coredump; /* Now dump all of the user data. Include malloced stuff as well */ - if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump))) + if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump))) goto end_coredump; /* now we start writing out the user space info */ set_fs(USER_DS); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 4f7dda9d86b5..c56ae3264a65 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -2162,7 +2162,7 @@ static int elf_core_dump(struct coredump_params *cprm) goto end_coredump; /* Align to page */ - if (!dump_seek(cprm->file, dataoff - cprm->written)) + if (!dump_skip(cprm, dataoff - cprm->written)) goto end_coredump; for (vma = first_vma(current, gate_vma); vma != NULL; @@ -2183,7 +2183,7 @@ static int elf_core_dump(struct coredump_params *cprm) kunmap(page); page_cache_release(page); } else - stop = !dump_seek(cprm->file, PAGE_SIZE); + stop = !dump_skip(cprm, PAGE_SIZE); if (stop) goto end_coredump; } diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 70e299917898..a69fc4ae1c85 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1509,7 +1509,7 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) kunmap(page); page_cache_release(page); } else { - res = dump_seek(file, PAGE_SIZE); + res = dump_skip(cprm, PAGE_SIZE); } if (!res) return false; @@ -1547,11 +1547,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) int has_dumped = 0; mm_segment_t fs; int segs; - size_t size = 0; int i; struct vm_area_struct *vma; struct elfhdr *elf = NULL; - loff_t offset = 0, dataoff, foffset; + loff_t offset = 0, dataoff; int numnote; struct memelfnote *notes = NULL; struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ @@ -1682,7 +1681,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) offset += sizeof(*elf); /* Elf header */ offset += segs * sizeof(struct elf_phdr); /* Program headers */ - foffset = offset; /* Write notes phdr entry */ { @@ -1751,8 +1749,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) if (!elf_core_write_extra_phdrs(cprm, offset)) goto end_coredump; - size = cprm->written; - cprm->written = foffset; /* write out the notes section */ for (i = 0; i < numnote; i++) if (!writenote(notes + i, cprm)) @@ -1768,10 +1764,9 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) goto end_coredump; } - if (!dump_seek(cprm->file, dataoff - cprm->written)) + if (!dump_skip(cprm, dataoff - cprm->written)) goto end_coredump; - cprm->written = size; if (!elf_fdpic_dump_segments(cprm)) goto end_coredump; diff --git a/fs/coredump.c b/fs/coredump.c index 2472ed9e682c..18baf2c009d4 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -685,14 +685,6 @@ void do_coredump(siginfo_t *siginfo) * do on a core-file: use only these functions to write out all the * necessary info. */ -int dump_write(struct file *file, const void *addr, int nr) -{ - return !dump_interrupted() && - access_ok(VERIFY_READ, addr, nr) && - file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} -EXPORT_SYMBOL(dump_write); - int dump_emit(struct coredump_params *cprm, const void *addr, int nr) { struct file *file = cprm->file; @@ -714,32 +706,25 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr) } EXPORT_SYMBOL(dump_emit); -int dump_seek(struct file *file, loff_t off) +int dump_skip(struct coredump_params *cprm, size_t nr) { - int ret = 1; - + static char zeroes[PAGE_SIZE]; + struct file *file = cprm->file; if (file->f_op->llseek && file->f_op->llseek != no_llseek) { + if (cprm->written + nr > cprm->limit) + return 0; if (dump_interrupted() || - file->f_op->llseek(file, off, SEEK_CUR) < 0) + file->f_op->llseek(file, nr, SEEK_CUR) < 0) return 0; + cprm->written += nr; + return 1; } else { - char *buf = (char *)get_zeroed_page(GFP_KERNEL); - - if (!buf) - return 0; - while (off > 0) { - unsigned long n = off; - - if (n > PAGE_SIZE) - n = PAGE_SIZE; - if (!dump_write(file, buf, n)) { - ret = 0; - break; - } - off -= n; + while (nr > PAGE_SIZE) { + if (!dump_emit(cprm, zeroes, PAGE_SIZE)) + return 0; + nr -= PAGE_SIZE; } - free_page((unsigned long)buf); + return dump_emit(cprm, zeroes, nr); } - return ret; } -EXPORT_SYMBOL(dump_seek); +EXPORT_SYMBOL(dump_skip); diff --git a/include/linux/coredump.h b/include/linux/coredump.h index 2959376a9ad5..07a0af93f230 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -11,8 +11,7 @@ * functions to write out all the necessary info. */ struct coredump_params; -extern int dump_write(struct file *file, const void *addr, int nr); -extern int dump_seek(struct file *file, loff_t off); +extern int dump_skip(struct coredump_params *cprm, size_t nr); extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); #ifdef CONFIG_COREDUMP extern void do_coredump(siginfo_t *siginfo);