Print this page
Merge hell test
@@ -25,10 +25,11 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2019 Joyent, Inc.
+ * Copyright 2021 Oxide Computer Company
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/thread.h>
@@ -92,16 +93,18 @@
size_t, size_t *, size_t *);
#ifdef _ELF32_COMPAT
/* Link against the non-compat instances when compiling the 32-bit version. */
extern size_t elf_datasz_max;
+extern size_t elf_zeropg_sz;
extern void elf_ctx_resize_scratch(elf_core_ctx_t *, size_t);
extern uint_t elf_nphdr_max;
extern uint_t elf_nshdr_max;
extern size_t elf_shstrtab_max;
#else
size_t elf_datasz_max = 1 * 1024 * 1024;
+size_t elf_zeropg_sz = 4 * 1024;
uint_t elf_nphdr_max = 1000;
uint_t elf_nshdr_max = 10000;
size_t elf_shstrtab_max = 100 * 1024;
#endif
@@ -2262,11 +2265,11 @@
u_offset_t poffset, soffset, doffset;
int error;
uint_t i, nphdrs, nshdrs;
struct seg *seg;
struct as *as = p->p_as;
- void *bigwad;
+ void *bigwad, *zeropg = NULL;
size_t bigsize, phdrsz, shdrsz;
Ehdr *ehdr;
Phdr *phdr;
Shdr shdr0;
caddr_t brkbase, stkbase;
@@ -2574,23 +2577,53 @@
if (phdr[i].p_filesz == 0)
continue;
/*
+ * If we hit a region that was mapped PROT_NONE then we cannot
+ * continue dumping this normally as the kernel would be unable
+ * to read from the page and that would result in us failing to
+ * dump the page. As such, any region mapped PROT_NONE, we dump
+ * as a zero-filled page such that this is still represented in
+ * the map.
+ *
* If dumping out this segment fails, rather than failing
* the core dump entirely, we reset the size of the mapping
* to zero to indicate that the data is absent from the core
* file and or in the PF_SUNW_FAILURE flag to differentiate
* this from mappings that were excluded due to the core file
* content settings.
*/
- if ((error = core_seg(p, vp, phdr[i].p_offset,
- (caddr_t)(uintptr_t)phdr[i].p_vaddr, phdr[i].p_filesz,
- rlimit, credp)) == 0) {
- continue;
+ if ((phdr[i].p_flags & (PF_R | PF_W | PF_X)) == 0) {
+ size_t towrite = phdr[i].p_filesz;
+ size_t curoff = 0;
+
+ if (zeropg == NULL) {
+ zeropg = kmem_zalloc(elf_zeropg_sz, KM_SLEEP);
}
+ error = 0;
+ while (towrite != 0) {
+ size_t len = MIN(towrite, elf_zeropg_sz);
+
+ error = core_write(vp, UIO_SYSSPACE,
+ phdr[i].p_offset + curoff, zeropg, len,
+ rlimit, credp);
+ if (error != 0)
+ break;
+
+ towrite -= len;
+ curoff += len;
+ }
+ } else {
+ error = core_seg(p, vp, phdr[i].p_offset,
+ (caddr_t)(uintptr_t)phdr[i].p_vaddr,
+ phdr[i].p_filesz, rlimit, credp);
+ }
+ if (error == 0)
+ continue;
+
if ((sig = lwp->lwp_cursig) == 0) {
/*
* We failed due to something other than a signal.
* Since the space reserved for the segment is now
* unused, we stash the errno in the first four