Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

coredump: Only sort VMAs when core_sort_vma sysctl is set

The sorting of VMAs by size in commit 7d442a33bfe8 ("binfmt_elf: Dump
smaller VMAs first in ELF cores") breaks elfutils[1]. Instead, sort
based on the setting of the new sysctl, core_sort_vma, which defaults
to 0, no sorting.

Reported-by: Michael Stapelberg <michael@stapelberg.ch>
Closes: https://lore.kernel.org/all/20250218085407.61126-1-michael@stapelberg.de/ [1]
Fixes: 7d442a33bfe8 ("binfmt_elf: Dump smaller VMAs first in ELF cores")
Signed-off-by: Kees Cook <kees@kernel.org>

+24 -2
+11
Documentation/admin-guide/sysctl/kernel.rst
··· 212 212 This value defaults to 0. 213 213 214 214 215 + core_sort_vma 216 + ============= 217 + 218 + The default coredump writes VMAs in address order. By setting 219 + ``core_sort_vma`` to 1, VMAs will be written from smallest size 220 + to largest size. This is known to break at least elfutils, but 221 + can be handy when dealing with very large (and truncated) 222 + coredumps where the more useful debugging details are included 223 + in the smaller VMAs. 224 + 225 + 215 226 core_uses_pid 216 227 ============= 217 228
+13 -2
fs/coredump.c
··· 63 63 64 64 static int core_uses_pid; 65 65 static unsigned int core_pipe_limit; 66 + static unsigned int core_sort_vma; 66 67 static char core_pattern[CORENAME_MAX_SIZE] = "core"; 67 68 static int core_name_size = CORENAME_MAX_SIZE; 68 69 unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT; ··· 1027 1026 .extra1 = (unsigned int *)&core_file_note_size_min, 1028 1027 .extra2 = (unsigned int *)&core_file_note_size_max, 1029 1028 }, 1029 + { 1030 + .procname = "core_sort_vma", 1031 + .data = &core_sort_vma, 1032 + .maxlen = sizeof(int), 1033 + .mode = 0644, 1034 + .proc_handler = proc_douintvec_minmax, 1035 + .extra1 = SYSCTL_ZERO, 1036 + .extra2 = SYSCTL_ONE, 1037 + }, 1030 1038 }; 1031 1039 1032 1040 static int __init init_fs_coredump_sysctls(void) ··· 1266 1256 cprm->vma_data_size += m->dump_size; 1267 1257 } 1268 1258 1269 - sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta), 1270 - cmp_vma_size, NULL); 1259 + if (core_sort_vma) 1260 + sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta), 1261 + cmp_vma_size, NULL); 1271 1262 1272 1263 return true; 1273 1264 }