]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
coredump: Only sort VMAs when core_sort_vma sysctl is set
authorKees Cook <kees@kernel.org>
Wed, 19 Feb 2025 19:53:16 +0000 (11:53 -0800)
committerKees Cook <kees@kernel.org>
Mon, 24 Feb 2025 18:51:57 +0000 (10:51 -0800)
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>
Documentation/admin-guide/sysctl/kernel.rst
fs/coredump.c

index a43b78b4b64649fe937e0ebb6cb44a6201945204..dd49a89a62d3542fa1a599f318dff26589e1d57b 100644 (file)
@@ -212,6 +212,17 @@ pid>/``).
 This value defaults to 0.
 
 
+core_sort_vma
+=============
+
+The default coredump writes VMAs in address order. By setting
+``core_sort_vma`` to 1, VMAs will be written from smallest size
+to largest size. This is known to break at least elfutils, but
+can be handy when dealing with very large (and truncated)
+coredumps where the more useful debugging details are included
+in the smaller VMAs.
+
+
 core_uses_pid
 =============
 
index 591700e1b2ce689e09272f75849673495d38126b..4375c70144d0ad981f53a6744f1f9a46ae825006 100644 (file)
@@ -63,6 +63,7 @@ static void free_vma_snapshot(struct coredump_params *cprm);
 
 static int core_uses_pid;
 static unsigned int core_pipe_limit;
+static unsigned int core_sort_vma;
 static char core_pattern[CORENAME_MAX_SIZE] = "core";
 static int core_name_size = CORENAME_MAX_SIZE;
 unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT;
@@ -1026,6 +1027,15 @@ static const struct ctl_table coredump_sysctls[] = {
                .extra1         = (unsigned int *)&core_file_note_size_min,
                .extra2         = (unsigned int *)&core_file_note_size_max,
        },
+       {
+               .procname       = "core_sort_vma",
+               .data           = &core_sort_vma,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_douintvec_minmax,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = SYSCTL_ONE,
+       },
 };
 
 static int __init init_fs_coredump_sysctls(void)
@@ -1256,8 +1266,9 @@ static bool dump_vma_snapshot(struct coredump_params *cprm)
                cprm->vma_data_size += m->dump_size;
        }
 
-       sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta),
-               cmp_vma_size, NULL);
+       if (core_sort_vma)
+               sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta),
+                    cmp_vma_size, NULL);
 
        return true;
 }