Description
Describe the bug
When the .dynstr
section is expanded due to a longer rpath, and the binary has a PT_NOTE
segment, the program headers get updated in a way that's causing the .dynstr
section to overlap two PT_LOAD
segments.
I'm not sure what the implications are, but on a particular filesystem I've been using patchelf on, binaries are broken (mmap/mprotect errors in the dynamic loader or even segfaults). The above issue stands out.
gdb
warns about this:
warning: Loadable section ".dynstr" outside of ELF segments
Steps To Reproduce
Run patchelf on itself:
$ cd $(mktemp -d)
$ curl -Lfs https://github.com/NixOS/patchelf/releases/download/0.15.0/patchelf-0.15.0.tar.gz | tar -zx --strip-components=1 -f -
$ ./configure
$ make "LDFLAGS=-Wl,-rpath,/example -no-pie" "CXXFLAGS=-O2 -g -fno-pic" install prefix=$PWD/install -j
$ cd install/bin
$ cp patchelf patchelf.copy
$ ./patchelf --set-rpath /longer/path patchelf.copy
$ gdb -ex r --args ./patchelf.copy
Reading symbols from ./patchelf.copy...
warning: Loadable section ".dynstr" outside of ELF segments
Starting program: /tmp/tmp.3gvU6yERyd/install/bin/patchelf.copy
Notice: -no-pie
and -fno-pic
is required for me to trigger it.
Full details, see the binaries here https://github.com/NixOS/patchelf/files/9633732/bin.tar.gz.
Notice that the .dynstr
section is not listed in the bottom "Section to Segment mapping"
Before:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x403c40
Start of program headers: 64 (bytes into file)
Start of section headers: 170992 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400318 00000318
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.gnu.propert NOTE 0000000000400338 00000338
0000000000000020 0000000000000000 A 0 0 8
[ 3] .note.gnu.build-i NOTE 0000000000400358 00000358
0000000000000024 0000000000000000 A 0 0 4
[ 4] .note.ABI-tag NOTE 000000000040037c 0000037c
0000000000000020 0000000000000000 A 0 0 4
[ 5] .gnu.hash GNU_HASH 00000000004003a0 000003a0
000000000000005c 0000000000000000 A 6 0 8
[ 6] .dynsym DYNSYM 0000000000400400 00000400
0000000000000828 0000000000000018 A 7 1 8
[ 7] .dynstr STRTAB 0000000000400c28 00000c28
0000000000000e43 0000000000000000 A 0 0 1
[ 8] .gnu.version VERSYM 0000000000401a6c 00001a6c
00000000000000ae 0000000000000002 A 6 0 2
[ 9] .gnu.version_r VERNEED 0000000000401b20 00001b20
00000000000000f0 0000000000000000 A 7 3 8
[10] .rela.dyn RELA 0000000000401c10 00001c10
00000000000000c0 0000000000000018 A 6 0 8
[11] .rela.plt RELA 0000000000401cd0 00001cd0
0000000000000720 0000000000000018 AI 6 26 8
[12] .init PROGBITS 0000000000403000 00003000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000403020 00003020
00000000000004d0 0000000000000010 AX 0 0 16
[14] .plt.sec PROGBITS 00000000004034f0 000034f0
00000000000004c0 0000000000000010 AX 0 0 16
[15] .text PROGBITS 00000000004039b0 000039b0
0000000000012024 0000000000000000 AX 0 0 16
[16] .fini PROGBITS 00000000004159d4 000159d4
000000000000000d 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 0000000000416000 00016000
0000000000001d60 0000000000000000 A 0 0 32
[18] .eh_frame_hdr PROGBITS 0000000000417d60 00017d60
00000000000007e4 0000000000000000 A 0 0 4
[19] .eh_frame PROGBITS 0000000000418548 00018548
0000000000003138 0000000000000000 A 0 0 8
[20] .gcc_except_table PROGBITS 000000000041b680 0001b680
0000000000000e14 0000000000000000 A 0 0 4
[21] .init_array INIT_ARRAY 000000000041dca8 0001cca8
0000000000000010 0000000000000008 WA 0 0 8
[22] .fini_array FINI_ARRAY 000000000041dcb8 0001ccb8
0000000000000008 0000000000000008 WA 0 0 8
[23] .data.rel.ro PROGBITS 000000000041dcc0 0001ccc0
0000000000000118 0000000000000000 WA 0 0 32
[24] .dynamic DYNAMIC 000000000041ddd8 0001cdd8
0000000000000200 0000000000000010 WA 7 0 8
[25] .got PROGBITS 000000000041dfd8 0001cfd8
0000000000000010 0000000000000008 WA 0 0 8
[26] .got.plt PROGBITS 000000000041e000 0001d000
0000000000000278 0000000000000008 WA 0 0 8
[27] .data PROGBITS 000000000041e278 0001d278
0000000000000015 0000000000000000 WA 0 0 8
[28] .bss NOBITS 000000000041e2a0 0001d28d
0000000000000240 0000000000000000 WA 0 0 32
[29] .comment PROGBITS 0000000000000000 0001d28d
000000000000002b 0000000000000001 MS 0 0 1
[30] .symtab SYMTAB 0000000000000000 0001d2b8
0000000000002a18 0000000000000018 31 106 8
[31] .strtab STRTAB 0000000000000000 0001fcd0
0000000000009de1 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 00029ab1
000000000000013e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000002d8 0x00000000000002d8 R 0x8
INTERP 0x0000000000000318 0x0000000000400318 0x0000000000400318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000023f0 0x00000000000023f0 R 0x1000
LOAD 0x0000000000003000 0x0000000000403000 0x0000000000403000
0x00000000000129e1 0x00000000000129e1 R E 0x1000
LOAD 0x0000000000016000 0x0000000000416000 0x0000000000416000
0x0000000000006494 0x0000000000006494 R 0x1000
LOAD 0x000000000001cca8 0x000000000041dca8 0x000000000041dca8
0x00000000000005e5 0x0000000000000838 RW 0x1000
DYNAMIC 0x000000000001cdd8 0x000000000041ddd8 0x000000000041ddd8
0x0000000000000200 0x0000000000000200 RW 0x8
NOTE 0x0000000000000338 0x0000000000400338 0x0000000000400338
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000358 0x0000000000400358 0x0000000000400358
0x0000000000000044 0x0000000000000044 R 0x4
GNU_PROPERTY 0x0000000000000338 0x0000000000400338 0x0000000000400338
0x0000000000000020 0x0000000000000020 R 0x8
GNU_EH_FRAME 0x0000000000017d60 0x0000000000417d60 0x0000000000417d60
0x00000000000007e4 0x00000000000007e4 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x000000000001cca8 0x000000000041dca8 0x000000000041dca8
0x0000000000000358 0x0000000000000358 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
03 .init .plt .plt.sec .text .fini
04 .rodata .eh_frame_hdr .eh_frame .gcc_except_table
05 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss
06 .dynamic
07 .note.gnu.property
08 .note.gnu.build-id .note.ABI-tag
09 .note.gnu.property
10 .eh_frame_hdr
11
12 .init_array .fini_array .data.rel.ro .dynamic .got
After:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x403c40
Start of program headers: 64 (bytes into file)
Start of section headers: 175088 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 15
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .dynstr STRTAB 00000000003ff388 00000388
0000000000000e55 0000000000000000 A 0 0 8
[ 2] .dynsym DYNSYM 00000000004001e0 000011e0
0000000000000828 0000000000000018 A 1 1 8
[ 3] .gnu.hash GNU_HASH 0000000000400a08 00001a08
000000000000005c 0000000000000000 A 2 0 8
[ 4] .interp PROGBITS 0000000000400a68 00001a68
000000000000001c 0000000000000000 A 0 0 8
[ 5] .note.ABI-tag NOTE 0000000000400a88 00001a88
0000000000000020 0000000000000000 A 0 0 4
[ 6] .note.gnu.build-i NOTE 0000000000400aa8 00001aa8
0000000000000024 0000000000000000 A 0 0 4
[ 7] .note.gnu.propert NOTE 0000000000400ad0 00001ad0
0000000000000020 0000000000000000 A 0 0 8
[ 8] .gnu.version VERSYM 0000000000401a6c 00002a6c
00000000000000ae 0000000000000002 A 2 0 2
[ 9] .gnu.version_r VERNEED 0000000000401b20 00002b20
00000000000000f0 0000000000000000 A 1 3 8
[10] .rela.dyn RELA 0000000000401c10 00002c10
00000000000000c0 0000000000000018 A 2 0 8
[11] .rela.plt RELA 0000000000401cd0 00002cd0
0000000000000720 0000000000000018 AI 2 26 8
[12] .init PROGBITS 0000000000403000 00004000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000403020 00004020
00000000000004d0 0000000000000010 AX 0 0 16
[14] .plt.sec PROGBITS 00000000004034f0 000044f0
00000000000004c0 0000000000000010 AX 0 0 16
[15] .text PROGBITS 00000000004039b0 000049b0
0000000000012024 0000000000000000 AX 0 0 16
[16] .fini PROGBITS 00000000004159d4 000169d4
000000000000000d 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 0000000000416000 00017000
0000000000001d60 0000000000000000 A 0 0 32
[18] .eh_frame_hdr PROGBITS 0000000000417d60 00018d60
00000000000007e4 0000000000000000 A 0 0 4
[19] .eh_frame PROGBITS 0000000000418548 00019548
0000000000003138 0000000000000000 A 0 0 8
[20] .gcc_except_table PROGBITS 000000000041b680 0001c680
0000000000000e14 0000000000000000 A 0 0 4
[21] .init_array INIT_ARRAY 000000000041dca8 0001dca8
0000000000000010 0000000000000008 WA 0 0 8
[22] .fini_array FINI_ARRAY 000000000041dcb8 0001dcb8
0000000000000008 0000000000000008 WA 0 0 8
[23] .data.rel.ro PROGBITS 000000000041dcc0 0001dcc0
0000000000000118 0000000000000000 WA 0 0 32
[24] .dynamic DYNAMIC 000000000041ddd8 0001ddd8
0000000000000200 0000000000000010 WA 1 0 8
[25] .got PROGBITS 000000000041dfd8 0001dfd8
0000000000000010 0000000000000008 WA 0 0 8
[26] .got.plt PROGBITS 000000000041e000 0001e000
0000000000000278 0000000000000008 WA 0 0 8
[27] .data PROGBITS 000000000041e278 0001e278
0000000000000015 0000000000000000 WA 0 0 8
[28] .bss NOBITS 000000000041e2a0 0001e28d
0000000000000240 0000000000000000 WA 0 0 32
[29] .comment PROGBITS 0000000000000000 0001e28d
000000000000002b 0000000000000001 MS 0 0 1
[30] .symtab SYMTAB 0000000000000000 0001e2b8
0000000000002a18 0000000000000018 31 106 8
[31] .strtab STRTAB 0000000000000000 00020cd0
0000000000009de1 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 0002aab1
000000000000013e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x00000000003ff040 0x00000000003ff040
0x0000000000000348 0x0000000000000348 R 0x8
GNU_STACK 0x0000000000001000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
LOAD 0x0000000000000000 0x00000000003ff000 0x00000000003ff000
0x0000000000001000 0x0000000000001000 RW 0x1000
LOAD 0x0000000000001000 0x0000000000400000 0x0000000000400000
0x00000000000023f0 0x00000000000023f0 R 0x1000
GNU_PROPERTY 0x0000000000001338 0x0000000000400338 0x0000000000400338
0x0000000000000020 0x0000000000000020 R 0x8
INTERP 0x0000000000001a68 0x0000000000400a68 0x0000000000400a68
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
NOTE 0x0000000000001a88 0x0000000000400a88 0x0000000000400a88
0x0000000000000020 0x0000000000000020 R 0x4
NOTE 0x0000000000001aa8 0x0000000000400aa8 0x0000000000400aa8
0x0000000000000024 0x0000000000000024 R 0x4
NOTE 0x0000000000001ad0 0x0000000000400ad0 0x0000000000400ad0
0x0000000000000020 0x0000000000000020 R 0x8
LOAD 0x0000000000004000 0x0000000000403000 0x0000000000403000
0x00000000000129e1 0x00000000000129e1 R E 0x1000
LOAD 0x0000000000017000 0x0000000000416000 0x0000000000416000
0x0000000000006494 0x0000000000006494 R 0x1000
GNU_EH_FRAME 0x0000000000018d60 0x0000000000417d60 0x0000000000417d60
0x00000000000007e4 0x00000000000007e4 R 0x4
LOAD 0x000000000001dca8 0x000000000041dca8 0x000000000041dca8
0x00000000000005e5 0x0000000000000838 RW 0x1000
GNU_RELRO 0x000000000001dca8 0x000000000041dca8 0x000000000041dca8
0x0000000000000358 0x0000000000000358 R 0x1
DYNAMIC 0x000000000001ddd8 0x000000000041ddd8 0x000000000041ddd8
0x0000000000000200 0x0000000000000200 RW 0x8
Section to Segment mapping:
Segment Sections...
00
01
02
03 .dynsym .gnu.hash .interp .note.ABI-tag .note.gnu.build-id .note.gnu.property .gnu.version .gnu.version_r .rela.dyn .rela.plt
04
05 .interp
06 .note.ABI-tag
07 .note.gnu.build-id
08 .note.gnu.property
09 .init .plt .plt.sec .text .fini
10 .rodata .eh_frame_hdr .eh_frame .gcc_except_table
11 .eh_frame_hdr
12 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss
13 .init_array .fini_array .data.rel.ro .dynamic .got
14 .dynamic