Fedora Account System
Red Hat Associate
Red Hat Customer
Description of problem: gdb aborts with a glibc heap error (SIGABRT, "free(): double free detected in tcache 2") when opening a core file that contains the same file-backed mapping name at two non-adjacent address ranges with many other distinct mapped files in between. This is the normal memory layout of KDE / Wayland programs, whose "/memfd:wayland-shm (deleted)" mappings appear several times scattered across the address space. Because ABRT runs gdb to generate a backtrace for every crashed program, every crash of a KDE/Wayland application makes gdb itself crash, so no usable backtrace is produced and coredumpctl fills up with "gdb killed by SIGABRT". Version-Release number of selected component: gdb-17.2-1.fc44 (also reproducible with the same code in current upstream; introduced by the core_mapped_file / gdb_read_core_file_mappings refactor, present since GDB 16). How reproducible: Always, given a matching core file. Steps to Reproduce: A self-contained reproducer (no KDE needed): /* gdb-corefile-doublefree-reproducer.c */ #define _GNU_SOURCE #include <sys/mman.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define N 200 #define PAGE 4096 int main(void) { long total = (long)(N + 2) * PAGE; char *base = mmap(NULL, total, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); int shared = memfd_create("wayland-shm", 0); ftruncate(shared, PAGE); mmap(base, PAGE, PROT_READ, MAP_SHARED | MAP_FIXED, shared, 0); for (int i = 0; i < N; i++) { char nm[32]; snprintf(nm, sizeof nm, "distinct-%d", i); int fd = memfd_create(nm, 0); ftruncate(fd, PAGE); mmap(base + (long)(i + 1) * PAGE, PAGE, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0); } mmap(base + (long)(N + 1) * PAGE, PAGE, PROT_READ, MAP_SHARED | MAP_FIXED, shared, 0); abort(); } gcc -g -O0 -o rep gdb-corefile-doublefree-reproducer.c ./rep coredumpctl dump ./rep --output=rep.core gdb -batch -ex 'set debuginfod enabled off' \ -ex 'file ./rep' -ex 'core-file ./rep.core' Actual results: warning: Can't open file /memfd:wayland-shm (deleted) during file-backed mapping note processing free(): double free detected in tcache 2 A fatal error internal to GDB has been detected, further debugging is not possible. GDB will now terminate. Backtrace of the abort: #6 malloc_printerr malloc.c:5341 #7 tcache_double_free_verify malloc.c:3159 #8 core_target::build_file_mappings() corelow.c:582 (vector<core_mapped_file> dtor) #9 core_target::core_target() corelow.c:351 #10 core_target_open(char const*, int) corelow.c Expected results: gdb loads the core file and prints a normal backtrace. Additional info / root cause: gdb_read_core_file_mappings() in gdb/corelow.c builds a std::vector<core_mapped_file> results, and its internal map_entry keeps a raw core_mapped_file* pointing into that vector: results.emplace_back (); map_entry entry (&results.back ()); // raw pointer into results ... core_mapped_file &file_data = *iter->second.file_data; file_data.regions.emplace_back (start, end, file_ofs); Every new distinct filename does another results.emplace_back(), which can reallocate the vector and leave all previously stored file_data pointers dangling. When a filename recurs at a later, non-adjacent address (e.g. the second wayland-shm mapping), file_data is a stale pointer and the regions.emplace_back writes into freed memory -> heap corruption -> abort when results is destroyed at the end of build_file_mappings(). The pre-loop callback is already handed the exact mapping count (pre_loop_cb(count) in linux-tdep.c) but currently ignores it. Reserving results up front (the number of distinct filenames is at most the mapping count) prevents the reallocation and fixes the crash: --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ gdb_read_core_file_mappings, pre-loop lambda - [&] (ULONGEST) + [&] (ULONGEST count) { + /* Reserve so RESULTS never reallocates while the per-mapping + lambda runs; each map_entry holds a raw core_mapped_file* + into RESULTS that would otherwise dangle on reallocation. */ + results.reserve (count); }, With this one-line change the reproducer above and real KDE/Wayland core files load correctly and produce a proper backtrace.
Created attachment 2148107 [details] Proposed one-line fix: reserve() in gdb_read_core_file_mappings (corelow.c)
Created attachment 2148108 [details] Self-contained minimal reproducer (no KDE required)
*** This bug has been marked as a duplicate of bug 2498034 ***