public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
* [Bug shlibs/30663] New: Segfault when reading malformed PT_INTERP header
@ 2023-07-21 20:03 mattlloydhouse at gmail dot com
  2024-01-18  4:06 ` [Bug shlibs/30663] " bgray at linux dot ibm.com
  0 siblings, 1 reply; 2+ messages in thread
From: mattlloydhouse at gmail dot com @ 2023-07-21 20:03 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=30663

            Bug ID: 30663
           Summary: Segfault when reading malformed PT_INTERP header
           Product: gdb
           Version: HEAD
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: shlibs
          Assignee: unassigned at sourceware dot org
          Reporter: mattlloydhouse at gmail dot com
  Target Milestone: ---

Created attachment 14995
  --> https://sourceware.org/bugzilla/attachment.cgi?id=14995&action=edit
The program used for reproduction.

In find_program_interpreter() in gdb/solib-svr4.c, if there isn't a current
exec_bfd, then the interpreter string is read using
read_program_header(PT_INTERP), which reads phdr->p_memsz bytes starting at
phdr->p_vaddr in inferior memory. This may return an empty byte vector, or a
vector that is not null-terminated. (The Linux kernel's ELF loader only
verifies that the phdr->p_filesz bytes starting at phdr->p_offset in the file
are null-terminated.)

However, enable_break() in gdb/solib-svr4.c passes a pointer to the byte
vector's buffer to solib_bfd_open(), which passes it to solib_find(), which
calls xstrdup() to copy it. If the byte vector is empty (i.e., phdr->p_memsz ==
0), then its buffer is set to a null pointer, and this raises a segfault.
Presumably, other issues can occur if the vector otherwise isn't
null-terminated.

I can reproduce this on the latest snapshot by writing an ELF program with
ehdr->e_ident[EI_VERSION] == EV_NONE to prevent the file from being loaded by
GDB, and phdr->p_memsz == 0 on the PT_INTERP header to cause the segfault.
Then, I run it indirectly via env(1).

$ xxd -r <<EOF > program
00000000: 7f45 4c46 0201 0003 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 0000 0000 0000 0000  ..>.............
00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0200 4000 0000 0000  ....@.8...@.....
00000040: 0300 0000 0400 0000 b000 0000 0000 0000  ................
00000050: b000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 1c00 0000 0000 0000 0000 0000 0000 0000  ................
00000070: 0000 0000 0000 0000 0100 0000 0500 0000  ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000090: 0000 0000 0000 0000 cc00 0000 0000 0000  ................
000000a0: cc00 0000 0000 0000 0000 0000 0000 0000  ................
000000b0: 2f6c 6962 3634 2f6c 642d 6c69 6e75 782d  /lib64/ld-linux-
000000c0: 7838 362d 3634 2e73 6f2e 3200            x86-64.so.2.
EOF
$ chmod +x program
$ gdb --args env ./program 
GNU gdb (GDB) 14.0.50.20230721-git
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from env...
(No debugging symbols found in env)
(gdb) run
Starting program: /usr/bin/env ./program
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
process 1096118 is executing new program: /home/lm978/program
warning: "/home/lm978/program": not in executable format: file format not
recognized
warning: `/home/lm978/program': can't read symbols: file format not recognized.


Fatal signal: Segmentation fault
----- Backtrace -----
0x56522c29ff90 gdb_internal_backtrace_1
    /home/lm978/gdb-14.0.50.20230721/gdb/bt-utils.c:122
0x56522c29ff90 _Z22gdb_internal_backtracev
    /home/lm978/gdb-14.0.50.20230721/gdb/bt-utils.c:168
0x56522c3c695e handle_fatal_signal
    /home/lm978/gdb-14.0.50.20230721/gdb/event-top.c:889
0x56522c3c6b18 handle_sigsegv
    /home/lm978/gdb-14.0.50.20230721/gdb/event-top.c:962
0x7fd3cf2c451f ???
    ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x7fd3cf41f97d ???
    ../sysdeps/x86_64/multiarch/strlen-avx2.S:74
0x56522c7bc352 xstrdup
    ./xstrdup.c:33
0x56522c57ca8d solib_find_1
    /home/lm978/gdb-14.0.50.20230721/gdb/solib.c:184
0x56522c57d71a _Z10solib_findPKcPi
    /home/lm978/gdb-14.0.50.20230721/gdb/solib.c:419
0x56522c57d842 _Z14solib_bfd_openPKc
    /home/lm978/gdb-14.0.50.20230721/gdb/solib.c:456
0x56522c57873e enable_break
    /home/lm978/gdb-14.0.50.20230721/gdb/solib-svr4.c:2444
0x56522c57873e svr4_solib_create_inferior_hook
    /home/lm978/gdb-14.0.50.20230721/gdb/solib-svr4.c:3163
0x56522c461c8e _ZNKSt8functionIFvP8inferiorS1_EEclES1_S1_
    /usr/include/c++/11/bits/std_function.h:590
0x56522c461c8e _ZNK3gdb9observers10observableIJP8inferiorS3_EE6notifyES3_S3_
    ./../gdbsupport/observable.h:166
0x56522c461c8e follow_exec
    /home/lm978/gdb-14.0.50.20230721/gdb/infrun.c:1371
0x56522c461c8e handle_inferior_event
    /home/lm978/gdb-14.0.50.20230721/gdb/infrun.c:6051
0x56522c462aca _Z20fetch_inferior_eventv
    /home/lm978/gdb-14.0.50.20230721/gdb/infrun.c:4462
0x56522c7ce755 gdb_wait_for_event
    /home/lm978/gdb-14.0.50.20230721/gdbsupport/event-loop.cc:694
0x56522c7cf1e9 gdb_wait_for_event
    /home/lm978/gdb-14.0.50.20230721/gdbsupport/event-loop.cc:593
0x56522c7cf1e9 _Z16gdb_do_one_eventi
    /home/lm978/gdb-14.0.50.20230721/gdbsupport/event-loop.cc:217
0x56522c4ade89 start_event_loop
    /home/lm978/gdb-14.0.50.20230721/gdb/main.c:412
0x56522c4ade89 captured_command_loop
    /home/lm978/gdb-14.0.50.20230721/gdb/main.c:476
0x56522c4b0394 captured_main
    /home/lm978/gdb-14.0.50.20230721/gdb/main.c:1320
0x56522c4b0394 _Z8gdb_mainP18captured_main_args
    /home/lm978/gdb-14.0.50.20230721/gdb/main.c:1339
0x56522c1e6ccf main
    /home/lm978/gdb-14.0.50.20230721/gdb/gdb.c:32
---------------------
A fatal error internal to GDB has been detected, further
debugging is not possible.  GDB will now terminate.

This is a bug, please report it.  For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.

Segmentation fault (core dumped)

System info:

$ uname -a
Linux firmament 5.15.0-75-generic #82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023
x86_64 x86_64 x86_64 GNU/Linux
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
11.3.0-1ubuntu1~22.04.1' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs
--enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr
--with-gcc-major-version-only --program-suffix=-11
--program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib
--enable-libphobos-checking=release --with-target-system-zlib=auto
--enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet
--with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32
--enable-multilib --with-tune=generic
--enable-offload-targets=nvptx-none=/build/gcc-11-aYxV0E/gcc-11-11.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-aYxV0E/gcc-11-11.3.0/debian/tmp-gcn/usr
--without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
--with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04.1)

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Bug shlibs/30663] Segfault when reading malformed PT_INTERP header
  2023-07-21 20:03 [Bug shlibs/30663] New: Segfault when reading malformed PT_INTERP header mattlloydhouse at gmail dot com
@ 2024-01-18  4:06 ` bgray at linux dot ibm.com
  0 siblings, 0 replies; 2+ messages in thread
From: bgray at linux dot ibm.com @ 2024-01-18  4:06 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=30663

Benjamin Gray <bgray at linux dot ibm.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bgray at linux dot ibm.com

--- Comment #1 from Benjamin Gray <bgray at linux dot ibm.com> ---
Ran into this myself and came here to report it. My binary has a `.interp`
section, but it has size 0. The following section in gdb/solib-svr4.c
enable_break()

    std::optional<gdb::byte_vector> interp_name_holder
      = find_program_interpreter ();
    if (interp_name_holder)
      {
        const char *interp_name = (const char *) interp_name_holder->data ();

Only checks that a vector is present, not that it has allocated anything. So
interp_name is possibly a null pointer. This is propagated down the chain

solib_bfd_open()
  solib_find()
    solib_find_1()
      xstrdup()

which ultimately segfaults on the null pointer.

find_program_interpreter() itself is correctly locating the zero sized
`.interp` section, creating a gdb::byte_vector with size 0. This wraps the
std::vector type, which avoids an allocation for zero vectors. The
bfd_get_section_contents() call trivially returns true because it's 'found' the
contents of this zero sized section, so never touches the data buffer. 
(actually, it _might_ call memset() on the buffer, which is undefined behaviour
as far as I can tell after a quick search).

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-01-18  4:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-21 20:03 [Bug shlibs/30663] New: Segfault when reading malformed PT_INTERP header mattlloydhouse at gmail dot com
2024-01-18  4:06 ` [Bug shlibs/30663] " bgray at linux dot ibm.com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).