Skip to content

Commit c119fb6

Browse files
thejhgregkh
authored andcommitted
coredump: Also dump first pages of non-executable ELF libraries
commit 84158b7 upstream. When I rewrote the VMA dumping logic for coredumps, I changed it to recognize ELF library mappings based on the file being executable instead of the mapping having an ELF header. But turns out, distros ship many ELF libraries as non-executable, so the heuristic goes wrong... Restore the old behavior where FILTER(ELF_HEADERS) dumps the first page of any offset-0 readable mapping that starts with the ELF magic. This fix is technically layer-breaking a bit, because it checks for something ELF-specific in fs/coredump.c; but since we probably want to share this between standard ELF and FDPIC ELF anyway, I guess it's fine? And this also keeps the change small for backporting. Cc: [email protected] Fixes: 429a22e ("coredump: rework elf/elf_fdpic vma_dump_size() into common helper") Reported-by: Bill Messmer <[email protected]> Signed-off-by: Jann Horn <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7ad5ccc commit c119fb6

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

fs/coredump.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/fs.h>
4242
#include <linux/path.h>
4343
#include <linux/timekeeping.h>
44+
#include <linux/elf.h>
4445

4546
#include <linux/uaccess.h>
4647
#include <asm/mmu_context.h>
@@ -969,6 +970,8 @@ static bool always_dump_vma(struct vm_area_struct *vma)
969970
return false;
970971
}
971972

973+
#define DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER 1
974+
972975
/*
973976
* Decide how much of @vma's contents should be included in a core dump.
974977
*/
@@ -1028,9 +1031,20 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
10281031
* dump the first page to aid in determining what was mapped here.
10291032
*/
10301033
if (FILTER(ELF_HEADERS) &&
1031-
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ) &&
1032-
(READ_ONCE(file_inode(vma->vm_file)->i_mode) & 0111) != 0)
1033-
return PAGE_SIZE;
1034+
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
1035+
if ((READ_ONCE(file_inode(vma->vm_file)->i_mode) & 0111) != 0)
1036+
return PAGE_SIZE;
1037+
1038+
/*
1039+
* ELF libraries aren't always executable.
1040+
* We'll want to check whether the mapping starts with the ELF
1041+
* magic, but not now - we're holding the mmap lock,
1042+
* so copy_from_user() doesn't work here.
1043+
* Use a placeholder instead, and fix it up later in
1044+
* dump_vma_snapshot().
1045+
*/
1046+
return DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER;
1047+
}
10341048

10351049
#undef FILTER
10361050

@@ -1105,8 +1119,6 @@ int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
11051119
m->end = vma->vm_end;
11061120
m->flags = vma->vm_flags;
11071121
m->dump_size = vma_dump_size(vma, cprm->mm_flags);
1108-
1109-
vma_data_size += m->dump_size;
11101122
}
11111123

11121124
mmap_write_unlock(mm);
@@ -1116,6 +1128,23 @@ int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
11161128
return -EFAULT;
11171129
}
11181130

1131+
for (i = 0; i < *vma_count; i++) {
1132+
struct core_vma_metadata *m = (*vma_meta) + i;
1133+
1134+
if (m->dump_size == DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER) {
1135+
char elfmag[SELFMAG];
1136+
1137+
if (copy_from_user(elfmag, (void __user *)m->start, SELFMAG) ||
1138+
memcmp(elfmag, ELFMAG, SELFMAG) != 0) {
1139+
m->dump_size = 0;
1140+
} else {
1141+
m->dump_size = PAGE_SIZE;
1142+
}
1143+
}
1144+
1145+
vma_data_size += m->dump_size;
1146+
}
1147+
11191148
*vma_data_size_ptr = vma_data_size;
11201149
return 0;
11211150
}

0 commit comments

Comments
 (0)