diff --git a/gdb-fix-crash-when-reading-core.patch b/gdb-fix-crash-when-reading-core.patch new file mode 100644 index 0000000..c003fb4 --- /dev/null +++ b/gdb-fix-crash-when-reading-core.patch @@ -0,0 +1,220 @@ +From 31aceee86308321c2ef299e50773d0043e458e7f Mon Sep 17 00:00:00 2001 +From: Tom de Vries +Date: Thu, 1 Nov 2018 09:21:18 +0100 +Subject: [PATCH] [gdb] Fix gdb crash when reading core file + +Consider the test-case from this patch, compiled with O0. + +The executable segfaults, and generates a core dump: +... +$ ./a.out +Segmentation fault (core dumped) +... + +When loading the core file, limiting stack size to 4MB, gdb crashes: +... +$ ulimit -s 4096 +$ gdb -batch ./a.out core.saved +[New LWP 19379] +Segmentation fault (core dumped) +... + +The crash originates here in linux_vsyscall_range_raw, where we call alloca +with phdrs_size == 4194112 (roughly 4MB): +... + phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size); +... + +While for this test-case gdb runs fine with the system default stack limit of +8MB, there are cases reported of 12MB phdrs_size where gdb also crashes with +the system default stack limit. + +Fix this by using xmalloc instead of alloca, which prevents the crash provided +the stack limit is at least 112kb. + +Build and reg-tested on x86_64-linux. + +2018-11-06 Tom de Vries + + * linux-tdep.c (linux_vsyscall_range_raw): Use xmalloc to allocate + program headers. + + * gdb.base/many-headers.c: New test. + * gdb.base/many-headers.exp: New file. +--- + gdb/ChangeLog | 5 +++ + gdb/linux-tdep.c | 12 +++--- + gdb/testsuite/ChangeLog | 5 +++ + gdb/testsuite/gdb.base/many-headers.c | 50 ++++++++++++++++++++++++ + gdb/testsuite/gdb.base/many-headers.exp | 67 +++++++++++++++++++++++++++++++++ + 5 files changed, 133 insertions(+), 6 deletions(-) + create mode 100644 gdb/testsuite/gdb.base/many-headers.c + create mode 100644 gdb/testsuite/gdb.base/many-headers.exp + +diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c +index c958c0dfe9..2c766808f0 100644 +--- a/gdb/linux-tdep.c ++++ b/gdb/linux-tdep.c +@@ -2269,7 +2269,6 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range) + the vDSO. */ + if (!target_has_execution) + { +- Elf_Internal_Phdr *phdrs; + long phdrs_size; + int num_phdrs, i; + +@@ -2277,16 +2276,17 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range) + if (phdrs_size == -1) + return 0; + +- phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size); +- num_phdrs = bfd_get_elf_phdrs (core_bfd, phdrs); ++ gdb::unique_xmalloc_ptr ++ phdrs ((Elf_Internal_Phdr *) xmalloc (phdrs_size)); ++ num_phdrs = bfd_get_elf_phdrs (core_bfd, phdrs.get ()); + if (num_phdrs == -1) + return 0; + + for (i = 0; i < num_phdrs; i++) +- if (phdrs[i].p_type == PT_LOAD +- && phdrs[i].p_vaddr == range->start) ++ if (phdrs.get ()[i].p_type == PT_LOAD ++ && phdrs.get ()[i].p_vaddr == range->start) + { +- range->length = phdrs[i].p_memsz; ++ range->length = phdrs.get ()[i].p_memsz; + return 1; + } + +diff --git a/gdb/testsuite/gdb.base/many-headers.c b/gdb/testsuite/gdb.base/many-headers.c +new file mode 100644 +index 0000000000..49675b4e40 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/many-headers.c +@@ -0,0 +1,50 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2018 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++#include ++#include ++ ++int ++main (void) ++{ ++ char *ptr; ++ int ind, cnt; ++ ++ cnt = 100000; ++ for (ind = 0; ind < cnt; ind++) ++ { ++ ptr = mmap (NULL, 100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ++ if (ptr == NULL) ++ { ++ fprintf (stderr, "Error allocating memory using mmap\n"); ++ return -1; ++ } ++ ++ ptr = mmap (NULL, 100, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ++ if (ptr == NULL) ++ { ++ fprintf (stderr, "Error allocating memory using mmap\n"); ++ return -1; ++ } ++ } ++ ++ ptr = NULL; ++ *ptr = '\0'; ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/many-headers.exp b/gdb/testsuite/gdb.base/many-headers.exp +new file mode 100644 +index 0000000000..f02b291e36 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/many-headers.exp +@@ -0,0 +1,67 @@ ++# Copyright 2018 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# Test if gdb can read a core file with a program header size of 4MB, if the ++# stack size is limited to 4MB. ++ ++if { [target_info gdb_protocol] != "" } { ++ # Even though the feature under features being tested are supported by ++ # gdbserver, the way this test is written doesn't make it easy with a ++ # remote target. ++ unsupported "not native" ++ return ++} ++ ++standard_testfile ++ ++if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} { ++ return -1 ++} ++ ++# Generate core file. ++set corefile [core_find $binfile] ++if {$corefile == ""} { ++ return 0 ++} ++ ++# Limit is in kb, so this is 4MB. ++set stack_limit 4096 ++ ++# Verify if we can set the stack limit. ++catch { ++ system [concat \ ++ "(" \ ++ "ulimit -s $stack_limit;" \ ++ ")"] ++} msg ++if { "$msg" != "" } { ++ untested "Can't set stack limit" ++ return -1 ++} ++ ++# Run gdb with stack limit ++catch { ++ system [concat \ ++ "(" \ ++ "ulimit -s $stack_limit;" \ ++ "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS -batch -core=$corefile" \ ++ ")"] ++} msg ++set test "read core file" ++if { "$msg" == "" } { ++ pass "$test" ++} else { ++ fail "$test" ++} +-- +2.16.4 + diff --git a/gdb.changes b/gdb.changes index ec0ca9d..db491a7 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Wed Nov 7 15:04:28 UTC 2018 - tdevries@suse.com + +- Fix crash when reading core [bsc #1109013] + * Add gdb-fix-crash-when-reading-core.patch + https://sourceware.org/ml/gdb-cvs/2018-11/msg00022.html + ------------------------------------------------------------------- Tue Sep 11 15:01:59 UTC 2018 - matz@suse.com diff --git a/gdb.spec b/gdb.spec index 42eff94..d572515 100644 --- a/gdb.spec +++ b/gdb.spec @@ -240,6 +240,9 @@ Patch1004: gdb-fix-buf-overflow.diff Patch1005: gdb-7.10-swo18929.patch Patch1007: gdb-fix-s390-build.diff +# Backports from master +Patch2000: gdb-fix-crash-when-reading-core.patch + # libipt support Patch3000: v1.5-libipt-static.patch @@ -554,6 +557,8 @@ find -name "*.info*"|xargs rm -f %patch1005 -p1 %patch1007 -p1 +%patch2000 -p1 + #unpack libipt %if 0%{have_libipt} tar xzf %{SOURCE7}