Closed fish2bird closed 1 year ago
Describe the bug
patchelf may bring segfault on GoLang ELF, whose section headers follows program headers and no gap between SHdr and PHdr.
Steps To Reproduce
cat > hello-world.go <<EOF package main import "fmt" func main() { fmt.Println("hello world") } EOF go build -buildmode=pie hello-world.go patchelf --debug --no-sort --output ./patched1 --set-interpreter /lib64/ld-linux-x86-64.so.2 ./hello-world patchelf --debug --no-sort --output ./patched2 --set-interpreter /lib64/ld-linux-x86-64.so.2 ./patched1 ./patched2
Expected behavior
patchelf --version output
patchelf --version
patchelf 0.17.2
Additional context
for original file, Section Headers next to program headers:
offsetof(PHdrs) + sizeof(PHdrs[0]) * PHdrs.size() == offsetof(SHdrs)
Although first patch runs okay, but PHdrs(program headers) do overlap with SHdrs(Section Headers).
because new header added to PHdrs
offsetof(PHdrs) + sizeof(PHdrs[0]) * PHdrs.size() > offsetof(SHdrs)
details here:
[root tmp]#go version go version go1.15.7 linux/amd64 [root tmp]#readelf -e ./hello-world ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x4650a0 Start of program headers: 64 (bytes into file) Start of section headers: 736 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 12 Size of section headers: 64 (bytes) Number of section headers: 39 Section header string table index: 11 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000401000 00001000 0000000000098b4b 0000000000000000 AX 0 0 32 [ 2] .plt PROGBITS 0000000000499b50 00099b50 0000000000000010 0000000000000010 AX 0 0 16 ... (omited for read) ... [35] .interp PROGBITS 0000000000400fe4 00000fe4 000000000000001c 0000000000000000 A 0 0 1 [36] .note.go.buildid NOTE 0000000000400f80 00000f80 0000000000000064 0000000000000000 A 0 0 4 [37] .symtab SYMTAB 0000000000000000 00224000 0000000000011310 0000000000000018 38 422 8 [38] .strtab STRTAB 0000000000000000 00235310 0000000000010994 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 0x00000000000002a0 0x00000000000002a0 R 1000 INTERP 0x0000000000000fe4 0x0000000000400fe4 0x0000000000400fe4 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] ... (omited for read) ... TLS 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000008 R 8 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 8 LOOS+5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 8 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .note.go.buildid 03 .text .plt .interp .note.go.buildid 04 .rodata .gnu.version_r .rela .rela.plt .dynstr .gnu.version .hash .dynsym 05 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 06 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 07 .go.buildinfo .got.plt .dynamic .got .noptrdata .data .bss .noptrbss 08 .dynamic 09 .tbss 10 11 [root tmp]#./hello-world hello world [root tmp]#readelf -e ./patched1 ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x4650a0 Start of program headers: 64 (bytes into file) Start of section headers: 736 (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: 39 Section header string table index: 11 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] .text DYNAMIC 00000000005dd000 005dd000 0000000000000020 0000000000000000 xxxo 32 0 4096 [ 1] .text PROGBITS 0000000000401000 00001000 0000000000098b4b 0000000000000000 AX 0 0 32 [ 2] .plt PROGBITS 0000000000499b50 00099b50 0000000000000010 0000000000000010 AX 0 0 16 ... (omited for read) ... [35] .interp PROGBITS 00000000005dd000 00246000 000000000000001c 0000000000000000 A 0 0 8 [36] .note.go.buildid NOTE 0000000000400f80 00000f80 0000000000000064 0000000000000000 A 0 0 4 [37] .symtab SYMTAB 0000000000000000 00224000 0000000000011310 0000000000000018 38 422 8 [38] .strtab STRTAB 0000000000000000 00235310 0000000000010994 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 1000 INTERP 0x0000000000246000 0x00000000005dd000 0x00000000005dd000 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] ... (omited for read) ... GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 8 LOOS+5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 8 LOAD 0x0000000000246000 0x00000000005dd000 0x00000000005dd000 0x0000000000000020 0x0000000000000020 RW 1000 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .note.go.buildid 03 .text .plt .note.go.buildid 04 .rodata .gnu.version_r .rela .rela.plt .dynstr .gnu.version .hash .dynsym 05 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 06 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 07 .go.buildinfo .got.plt .dynamic .got .noptrdata .data .bss .noptrbss 08 .dynamic 09 .tbss 10 11 12 .interp [root tmp]#readelf -e ./patched2 ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x4650a0 Start of program headers: 64 (bytes into file) Start of section headers: 736 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 14 Size of section headers: 64 (bytes) Number of section headers: 39 Section header string table index: 11 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] .text DYNAMIC 00000000005dd000 005dd000 0000000000000020 0000000600000001 xxxo 32 0 4096 [ 1] .text PROGBITS 0000000000401000 00001000 0000000000098b4b 0000000000000000 AX 0 0 32 [ 2] .plt PROGBITS 0000000000499b50 00099b50 0000000000000010 0000000000000010 AX 0 0 16 ... (omited for read) ... [35] .interp PROGBITS 00000000005de000 00247000 000000000000001c 0000000000000000 A 0 0 8 [36] .note.go.buildid NOTE 0000000000400f80 00000f80 0000000000000064 0000000000000000 A 0 0 4 [37] .symtab SYMTAB 0000000000000000 00224000 0000000000011310 0000000000000018 38 422 8 [38] .strtab STRTAB 0000000000000000 00235310 0000000000010994 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 0x0000000000000310 0x0000000000000310 R 1000 INTERP 0x0000000000247000 0x00000000005de000 0x00000000005de000 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] ... (omited for read) ... GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 8 LOOS+5041580 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 8 LOAD 0x0000000000246000 0x00000000005dd000 0x00000000005dd000 0x0000000000000020 0x0000000000000020 RW 1000 LOAD 0x0000000100000001 0x0000000000000006 0x0000000000401000 0x0000000000001000 0x0000000000098b4b RW 0 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .note.go.buildid 03 .text .plt .note.go.buildid 04 .rodata .gnu.version_r .rela .rela.plt .dynstr .gnu.version .hash .dynsym 05 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 06 .data.rel.ro .data.rel.ro.typelink .data.rel.ro.itablink .data.rel.ro.gosymtab .data.rel.ro.gopclntab 07 .go.buildinfo .got.plt .dynamic .got .noptrdata .data .bss .noptrbss 08 .dynamic 09 .tbss 10 11 12 13
here is full record
Fixed with #460
Describe the bug
patchelf may bring segfault on GoLang ELF, whose section headers follows program headers and no gap between SHdr and PHdr.
Steps To Reproduce
Expected behavior
patchelf --version
outputpatchelf 0.17.2
Additional context
for original file, Section Headers next to program headers:
Although first patch runs okay, but PHdrs(program headers) do overlap with SHdrs(Section Headers).
because new header added to PHdrs
details here:
here is full record