Date: Thu, 26 Jan 2017 09:46:34 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r312794 - stable/11/sys/kern Message-ID: <201701260946.v0Q9kYet021336@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Thu Jan 26 09:46:34 2017 New Revision: 312794 URL: https://svnweb.freebsd.org/changeset/base/312794 Log: MFC r312532: don't abort writing of a core dump after EFAULT Modified: stable/11/sys/kern/imgact_elf.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/kern/imgact_elf.c ============================================================================== --- stable/11/sys/kern/imgact_elf.c Thu Jan 26 07:07:09 2017 (r312793) +++ stable/11/sys/kern/imgact_elf.c Thu Jan 26 09:46:34 2017 (r312794) @@ -1160,7 +1160,7 @@ struct coredump_params { static void cb_put_phdr(vm_map_entry_t, void *); static void cb_size_segment(vm_map_entry_t, void *); -static int core_write(struct coredump_params *, void *, size_t, off_t, +static int core_write(struct coredump_params *, const void *, size_t, off_t, enum uio_seg); static void each_writable_segment(struct thread *, segment_callback, void *); static int __elfN(corehdr)(struct coredump_params *, int, void *, size_t, @@ -1202,7 +1202,14 @@ compress_chunk(struct coredump_params *p while (len > 0) { chunk_len = MIN(len, CORE_BUF_SIZE); - copyin(base, buf, chunk_len); + + /* + * We can get EFAULT error here. + * In that case zero out the current chunk of the segment. + */ + error = copyin(base, buf, chunk_len); + if (error != 0) + bzero(buf, chunk_len); error = gzio_write(p->gzs, buf, chunk_len); if (error != 0) break; @@ -1222,12 +1229,12 @@ core_gz_write(void *base, size_t len, of #endif /* GZIO */ static int -core_write(struct coredump_params *p, void *base, size_t len, off_t offset, - enum uio_seg seg) +core_write(struct coredump_params *p, const void *base, size_t len, + off_t offset, enum uio_seg seg) { - return (vn_rdwr_inchunks(UIO_WRITE, p->vp, base, len, offset, - seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED, + return (vn_rdwr_inchunks(UIO_WRITE, p->vp, __DECONST(void *, base), + len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED, p->active_cred, p->file_cred, NULL, p->td)); } @@ -1235,12 +1242,32 @@ static int core_output(void *base, size_t len, off_t offset, struct coredump_params *p, void *tmpbuf) { + int error; #ifdef GZIO if (p->gzs != NULL) return (compress_chunk(p, base, tmpbuf, len)); #endif - return (core_write(p, base, len, offset, UIO_USERSPACE)); + /* + * EFAULT is a non-fatal error that we can get, for example, + * if the segment is backed by a file but extends beyond its + * end. + */ + error = core_write(p, base, len, offset, UIO_USERSPACE); + if (error == EFAULT) { + log(LOG_WARNING, "Failed to fully fault in a core file segment " + "at VA %p with size 0x%zx to be written at offset 0x%jx " + "for process %s\n", base, len, offset, curproc->p_comm); + + /* + * Write a "real" zero byte at the end of the target region + * in the case this is the last segment. + * The intermediate space will be implicitly zero-filled. + */ + error = core_write(p, zero_region, 1, offset + len - 1, + UIO_SYSSPACE); + } + return (error); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201701260946.v0Q9kYet021336>