svn commit: r312794 - stable/11/sys/kern
Andriy Gapon
avg at FreeBSD.org
Thu Jan 26 09:46:35 UTC 2017
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);
}
/*
More information about the svn-src-stable-11
mailing list