summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2002-12-16 19:24:43 +0000
committerdillon <dillon@FreeBSD.org>2002-12-16 19:24:43 +0000
commitbe3db49c80fb516ad39e2306c2dd94eb57f1fe16 (patch)
tree62395793dfc1ca744a98bca2261e363d7c975367 /libexec
parent1696b05046d85a2bd2206eddc6e04c79ac567c2b (diff)
downloadFreeBSD-src-be3db49c80fb516ad39e2306c2dd94eb57f1fe16.zip
FreeBSD-src-be3db49c80fb516ad39e2306c2dd94eb57f1fe16.tar.gz
Change the way ELF coredumps are handled. Instead of unconditionally
skipping read-only pages, which can result in valuable non-text-related data not getting dumped, the ELF loader and the dynamic loader now mark read-only text pages NOCORE and the coredump code only checks (primarily) for complete inaccessibility of the page or NOCORE being set. Certain applications which map large amounts of read-only data will produce much larger cores. A new sysctl has been added, debug.elf_legacy_coredump, which will revert to the old behavior. This commit represents collaborative work by all parties involved. The PR contains a program demonstrating the problem. PR: kern/45994 Submitted by: "Peter Edwards" <pmedwards@eircom.net>, Archie Cobbs <archie@dellroad.org> Reviewed by: jdp, dillon MFC after: 7 days
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/map_object.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index a0220ef..7d45662 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -38,7 +38,8 @@
#include "debug.h"
#include "rtld.h"
-static int protflags(int); /* Elf flags -> mmap protection */
+static int convert_prot(int); /* Elf flags -> mmap protection */
+static int convert_flags(int); /* Elf flags -> mmap flags */
/*
* Map a shared object into memory. The "fd" argument is a file descriptor,
@@ -75,6 +76,7 @@ map_object(int fd, const char *path, const struct stat *sb)
Elf_Addr data_vlimit;
caddr_t data_addr;
int data_prot;
+ int data_flags;
Elf_Addr clear_vaddr;
caddr_t clear_addr;
caddr_t clear_page;
@@ -189,8 +191,8 @@ map_object(int fd, const char *path, const struct stat *sb)
mapsize = base_vlimit - base_vaddr;
base_addr = u.hdr.e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
- mapbase = mmap(base_addr, mapsize, protflags(segs[0]->p_flags),
- MAP_PRIVATE, fd, base_offset);
+ mapbase = mmap(base_addr, mapsize, convert_prot(segs[0]->p_flags),
+ convert_flags(segs[0]->p_flags), fd, base_offset);
if (mapbase == (caddr_t) -1) {
_rtld_error("%s: mmap of entire address space failed: %s",
path, strerror(errno));
@@ -209,10 +211,11 @@ map_object(int fd, const char *path, const struct stat *sb)
data_vaddr = trunc_page(segs[i]->p_vaddr);
data_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_filesz);
data_addr = mapbase + (data_vaddr - base_vaddr);
- data_prot = protflags(segs[i]->p_flags);
+ data_prot = convert_prot(segs[i]->p_flags);
+ data_flags = convert_flags(segs[i]->p_flags) | MAP_FIXED;
/* Do not call mmap on the first segment - this is redundant */
if (i && mmap(data_addr, data_vlimit - data_vaddr, data_prot,
- MAP_PRIVATE|MAP_FIXED, fd, data_offset) == (caddr_t) -1) {
+ data_flags, fd, data_offset) == (caddr_t) -1) {
_rtld_error("%s: mmap of data failed: %s", path, strerror(errno));
return NULL;
}
@@ -315,7 +318,7 @@ obj_new(void)
* flags for MMAP.
*/
static int
-protflags(int elfflags)
+convert_prot(int elfflags)
{
int prot = 0;
if (elfflags & PF_R)
@@ -326,3 +329,17 @@ protflags(int elfflags)
prot |= PROT_EXEC;
return prot;
}
+
+static int
+convert_flags(int elfflags)
+{
+ int flags = MAP_PRIVATE; /* All mappings are private */
+
+ /*
+ * Readonly mappings are marked "MAP_NOCORE", because they can be
+ * reconstructed by a debugger.
+ */
+ if (!(elfflags & PF_W))
+ flags |= MAP_NOCORE;
+ return flags;
+}
OpenPOWER on IntegriCloud