diff options
author | dillon <dillon@FreeBSD.org> | 2002-12-16 19:24:43 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2002-12-16 19:24:43 +0000 |
commit | be3db49c80fb516ad39e2306c2dd94eb57f1fe16 (patch) | |
tree | 62395793dfc1ca744a98bca2261e363d7c975367 /libexec/rtld-elf | |
parent | 1696b05046d85a2bd2206eddc6e04c79ac567c2b (diff) | |
download | FreeBSD-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/rtld-elf')
-rw-r--r-- | libexec/rtld-elf/map_object.c | 29 |
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; +} |