Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken binaries generated on mipsel #82

Closed
fsateler opened this issue Mar 1, 2016 · 5 comments
Closed

Broken binaries generated on mipsel #82

fsateler opened this issue Mar 1, 2016 · 5 comments

Comments

@fsateler
Copy link
Contributor

fsateler commented Mar 1, 2016

Tests failed on mipsel on debian:

FAIL: set-rpath.sh
==================

Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath/main'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 404
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x65e/0x40065e
first page is 0x400000
needed space is 1748
needed space is 1780
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17578 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 290) to offset 0x2dc (size 404)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x470 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5e0 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x688 (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x698 (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6b8 (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6dc (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./main: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL set-rpath.sh (exit status: 1)

FAIL: no-rpath.sh
=================

Kernel page size is 16384 bytes
Kernel page size is 16384 bytes
patching ELF file `scratch/no-rpath/no-rpath'
Kernel page size is 16384 bytes
new rpath is `/foo:/bar:/xxxxxxxxxxxxxxx'
rpath is too long, resizing...
DT_NULL index is 26
replacing section `.dynamic' with size 264
replacing section `.dynstr' with size 234
replacing section `.interp' with size 13
this is an executable
using replaced section `.interp'
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x518/0x400518
first page is 0x400000
needed space is 1336
needed space is 1368
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17252 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 256) to offset 0x1cc (size 264)
rewriting section `.dynstr' from offset 0x4448 (size 207) to offset 0x2d4 (size 234)
rewriting section `.dynsym' from offset 0x4368 (size 224) to offset 0x3c0 (size 224)
rewriting section `.hash' from offset 0x431c (size 76) to offset 0x4a0 (size 76)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x4ec (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x4fc (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x51c (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x540 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
Kernel page size is 16384 bytes
./no-rpath: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
FAIL no-rpath.sh (exit status: 127)

FAIL: big-dynstr.sh
===================

Kernel page size is 16384 bytes
patching ELF file `scratch/big-dynstr/big-dynstr'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/big-dynstr/libsA:/home/fsateler/patchelf/tests/scratch/big-dynstr/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 406
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x65e/0x40065e
first page is 0x400000
needed space is 1752
needed space is 1784
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17578 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 290) to offset 0x2dc (size 406)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x474 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5e4 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x68c (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x69c (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6bc (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6e0 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./big-dynstr: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL big-dynstr.sh (exit status: 1)

FAIL: set-rpath-library.sh
==========================

Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath-library/main-scoped'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 427
this is an executable
using replaced section `.dynamic'
using replaced section `.dynstr'
last replaced is 9
looking at section `.interp'
replacing section `.interp' which is in the way
looking at section `.note.ABI-tag'
replacing section `.note.ABI-tag' which is in the way
looking at section `.MIPS.abiflags'
replacing section `.MIPS.abiflags' which is in the way
looking at section `.reginfo'
replacing section `.reginfo' which is in the way
looking at section `.note.gnu.build-id'
replacing section `.note.gnu.build-id' which is in the way
looking at section `.dynamic'
looking at section `.hash'
replacing section `.hash' which is in the way
looking at section `.dynsym'
replacing section `.dynsym' which is in the way
looking at section `.dynstr'
first reserved offset/addr is 0x666/0x400666
first page is 0x400000
needed space is 1772
needed space is 1804
needed pages is 1
changing alignment of program header 4 from 65536 to 16384
changing alignment of program header 5 from 65536 to 16384
clearing first 17586 bytes
rewriting section `.MIPS.abiflags' from offset 0x41c8 (size 24) to offset 0x1b4 (size 24)
rewriting section `.dynamic' from offset 0x421c (size 264) to offset 0x1cc (size 272)
rewriting section `.dynstr' from offset 0x453c (size 297) to offset 0x2dc (size 427)
rewriting section `.dynsym' from offset 0x43cc (size 368) to offset 0x488 (size 368)
rewriting section `.hash' from offset 0x4324 (size 168) to offset 0x5f8 (size 168)
rewriting section `.interp' from offset 0x4194 (size 13) to offset 0x6a0 (size 13)
rewriting section `.note.ABI-tag' from offset 0x41a4 (size 32) to offset 0x6b0 (size 32)
rewriting section `.note.gnu.build-id' from offset 0x41f8 (size 36) to offset 0x6d0 (size 36)
rewriting section `.reginfo' from offset 0x41e0 (size 24) to offset 0x6f4 (size 24)
rewriting symbol table section 4
rewriting symbol table section 38
./main-scoped: error while loading shared libraries: libfoo-scoped.so: cannot open shared object file: No such file or directory
Kernel page size is 16384 bytes
patching ELF file `scratch/set-rpath-library/libsA/libfoo-scoped.so'
Kernel page size is 16384 bytes
new rpath is `/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB'
rpath is too long, resizing...
DT_NULL index is 27
replacing section `.dynamic' with size 272
replacing section `.dynstr' with size 324
this is a dynamic library
last page is 0x14000
needed space is 948
warning: working around a Linux kernel bug by creating a hole of 65536 bytes in ‘scratch/set-rpath-library/libsA/libfoo-scoped.so’
rewriting section `.dynamic' from offset 0x1cc (size 264) to offset 0x14160 (size 272)
rewriting section `.dynstr' from offset 0x4b0 (size 256) to offset 0x14270 (size 324)
rewriting symbol table section 5
rewriting symbol table section 34
./main-scoped: error while loading shared libraries: libfoo-scoped.so: cannot open shared object file: No such file or directory
bad exit code!
FAIL set-rpath-library.sh (exit status: 1)

Further debug shows that the library is found, it just can't be loaded because there is an invalid MIPS.abiflags:

 % LD_DEBUG=all  ./scratch/set-rpath-library/main-scoped
     27384:
     27384:     file=libfoo-scoped.so [0];  needed by ./scratch/set-rpath-library/main-scoped [0]
     27384:     find library=libfoo-scoped.so [0]; searching
     27384:      search path=/oops/tls/loongson3a:/oops/tls:/oops/loongson3a:/oops:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/loongson3a:/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB                (RUNPATH from file ./scratch/set-rpath-library/main-scoped)
     27384:       trying file=/oops/tls/loongson3a/libfoo-scoped.so
     27384:       trying file=/oops/tls/libfoo-scoped.so
     27384:       trying file=/oops/loongson3a/libfoo-scoped.so
     27384:       trying file=/oops/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/loongson3a/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/tls/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/loongson3a/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsA/libfoo-scoped.so
     27384:        : unknown MIPS.abiflags flags2: 1482184792
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/loongson3a/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/tls/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/loongson3a/libfoo-scoped.so
     27384:       trying file=/home/fsateler/patchelf/tests/scratch/set-rpath-library/libsB/libfoo-scoped.so

Further testing shows that this problem happens even when libfoo-scoped has not been touched. The problem appears to be when touching the main-scoped binary. So, I dug up the mentioned header, and indeed it is different in the touched binary:

 % readelf -x .MIPS.abiflags ./scratch/set-rpath-library/main-scoped ; readelf -x .MIPS.abiflags main-scoped

Hex dump of section '.MIPS.abiflags':
  0x003fc1b4 00000200 01010001 00000000 00000000 ................
  0x003fc1c4 00000000 00000000                   ........


Hex dump of section '.MIPS.abiflags':
  0x004001c8 00000200 01010001 00000000 00000000 ................
  0x004001d8 00000000 00000000                   ........

Why would patchelf modify a section it is not supposed to?

@fsateler
Copy link
Contributor Author

fsateler commented Mar 5, 2016

Hmm. On second look it is not different (the first column appears to be the address). Why would the first complain but the second not?

@fsateler
Copy link
Contributor Author

Some more information:

when creating a hello world executable and running patchelf --set-rpath / hello , the resulting binary fails with segmentation fault. The section headers where like this:

Elf file type is EXEC (Executable file)
Entry point 0x400570
There are 10 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00400034 0x00400034 0x00140 0x00140 R E 0x4
  INTERP         0x000174 0x00400174 0x00400174 0x0000d 0x0000d R   0x1
      [Requesting program interpreter: /lib/ld.so.1]
  ABIFLAGS       0x0001a8 0x004001a8 0x004001a8 0x00018 0x00018 R   0x8
  REGINFO        0x0001c0 0x004001c0 0x004001c0 0x00018 0x00018 R   0x4
  LOAD           0x000000 0x00400000 0x00400000 0x00884 0x00884 R E 0x10000
  LOAD           0x000884 0x00410884 0x00410884 0x00068 0x0007c RW  0x10000
  DYNAMIC        0x0001fc 0x004001fc 0x004001fc 0x00100 0x00100 R   0x4
  NOTE           0x000184 0x00400184 0x00400184 0x00020 0x00020 R   0x4
  NOTE           0x0001d8 0x004001d8 0x004001d8 0x00024 0x00024 R   0x4
  NULL           0x000000 0x00000000 0x00000000 0x00000 0x00000     0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .MIPS.abiflags 
   03     .reginfo 
   04     .interp .note.ABI-tag .MIPS.abiflags .reginfo .note.gnu.build-id .dynamic .hash .dynsym .dynstr .gnu.version .gnu.version_r .init .text .MIPS.stubs .fini .rodata .eh_frame 
   05     .init_array .fini_array .jcr .data .rld_map .got .sdata .bss 
   06     .dynamic 
   07     .note.ABI-tag 
   08     .note.gnu.build-id 
   09     

And ended up like this:

Elf file type is EXEC (Executable file)
Entry point 0x400570
There are 11 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x003fc034 0x003fc034 0x00160 0x00160 R E 0x4
  NULL           0x004000 0x00000000 0x00000000 0x00000 0x00000     0x4
  LOAD           0x000000 0x003fc000 0x003fc000 0x04000 0x04000 RW  0x4000
  DYNAMIC        0x0001ac 0x003fc1ac 0x003fc1ac 0x00108 0x00108 R   0x4
  INTERP         0x0004b4 0x003fc4b4 0x003fc4b4 0x0000d 0x0000d R   0x1
      [Requesting program interpreter: /lib/ld.so.1]
  LOAD           0x004000 0x00400000 0x00400000 0x00884 0x00884 R E 0x4000
  NOTE           0x004184 0x00400184 0x00400184 0x00020 0x00020 R   0x4
  ABIFLAGS       0x0041a8 0x004001a8 0x004001a8 0x00018 0x00018 R   0x8
  REGINFO        0x0041c0 0x004001c0 0x004001c0 0x00018 0x00018 R   0x4
  NOTE           0x0041d8 0x004001d8 0x004001d8 0x00024 0x00024 R   0x4
  LOAD           0x004884 0x00410884 0x00410884 0x00068 0x0007c RW  0x4000

 Section to Segment mapping:
  Segment Sections...
   00     
   01     
   02     .MIPS.abiflags .dynamic .dynstr .dynsym .hash .interp .note.ABI-tag .note.gnu.build-id .reginfo 
   03     .dynamic 
   04     .interp 
   05     .gnu.version .gnu.version_r .init .text .MIPS.stubs .fini .rodata .eh_frame 
   06     
   07     
   08     
   09     
   10     .init_array .fini_array .jcr .data .rld_map .got .sdata .bss

In particular, note that the MIPS.abiflags section is listed in 2 segments in the working executable, but only once in the broken one.

@fsateler
Copy link
Contributor Author

readelf -a output for both binaries here

@iv-m
Copy link
Contributor

iv-m commented Aug 22, 2019

when creating a hello world executable and running patchelf --set-rpath / hello , the resulting binary fails with segmentation fault.

This is still true for patchelf 0.10 on my mips32el machines. I digged into that a bit, and found that the problem is around the MIPS-specific mechanism of setting up the debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section is not zero, it holds the relative address of __RLD_MAP -- an offset relative to this dynamic section entry. Dynamic linker puts the pointer to r_debug structure there:

https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/rtld.c;h=453f56eb157b1795c86f9eddd2df45fcab9a0a9b#l1572
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mips/dl-machine.h;h=72165722d4678181381b69ce183deb8fdecb9529#l75

When patchelf updates the executable RPATH, it moves the .dynamic section both in the binary and in memory, while __RLD_MAP is not moved in memory, since it belongs to special .rld_map section that has type PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not valid anymore and should be updated. I'll check how this can be done in patchelf.

@iv-m
Copy link
Contributor

iv-m commented Aug 22, 2019

Further debug shows that the library is found, it just can't be loaded because there is an invalid MIPS.abiflags:

[...]
27384:        : unknown MIPS.abiflags flags2: 1482184792
[...]

1482184792 in hex is 0x58585858, and 0x58 is a code for character 'X'. So, the loader reads
some Xs, apparently written in the beginning of writeReplacedSections. So, while the section contents is not changed, the loader reads some wrong data.

The reason for that is that the dynamic loader does not look for the .MIPS.abiflags section -- it gets offset from PT_MIPS_ABIFLAGS header, which should be updated after the section is moved.

I'm testing the fix right now.

iv-m added a commit to iv-m/patchelf that referenced this issue Aug 22, 2019
`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.

The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is not zero, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.

When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.

This commit adds the necessary update.

Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.

Refs: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>

DT_MIPS_RLD_MAP_REL
iv-m added a commit to iv-m/patchelf that referenced this issue Aug 22, 2019
When loading the executable on MIPS, the dynamic loader looks for MIPS
ABI flags using PT_MIPS_ABIFLAGS header. The flags themselves are stored
in the .MIPS.abiflags section, so the header must be updated when the
section is moved.

Here we also import PT_MIPS_ABIFLAGS definition from glibc commit
0bd956720c457ff054325b48f26ac7c91cb060e8.

Closes: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
iv-m added a commit to iv-m/patchelf that referenced this issue Aug 22, 2019
`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.

The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is not zero, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.

When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.

This commit adds the necessary update.

Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.

Refs: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>

DT_MIPS_RLD_MAP_REL
iv-m added a commit to iv-m/patchelf that referenced this issue Aug 22, 2019
When loading the executable on MIPS, the dynamic loader looks for MIPS
ABI flags using PT_MIPS_ABIFLAGS header. The flags themselves are stored
in the .MIPS.abiflags section, so the header must be updated when the
section is moved.

Here we also import PT_MIPS_ABIFLAGS definition from glibc commit
0bd956720c457ff054325b48f26ac7c91cb060e8.

Closes: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
iv-m added a commit to iv-m/patchelf that referenced this issue Jun 21, 2021
`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.

The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is not zero, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.

When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.

This commit adds the necessary update.

Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.

Refs: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
iv-m added a commit to iv-m/patchelf that referenced this issue Jun 21, 2021
When loading the executable on MIPS, the dynamic loader looks for MIPS
ABI flags using PT_MIPS_ABIFLAGS header. The flags themselves are stored
in the .MIPS.abiflags section, so the header must be updated when the
section is moved.

Here we also import PT_MIPS_ABIFLAGS definition from glibc commit
0bd956720c457ff054325b48f26ac7c91cb060e8.

Closes: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
iv-m added a commit to iv-m/patchelf that referenced this issue Aug 11, 2021
`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.

The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is present, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.

When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.

This commit adds the necessary update.

In the corner case when DT_MIPS_RLD_MAP_REL is present, but
.rld_map section is not, the dynamic loader writes the debug
pointer to some arbitrary bytes in memory. To avoid crushes
on otherwise "working" binaries, we set offset to zero
so that the dynamic loader would just overwrite the dynamic
section.

Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.

Refs: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
@Mic92 Mic92 closed this as completed in bf73d6e Aug 11, 2021
haampie pushed a commit to haampie/patchelf that referenced this issue Nov 27, 2021
`patchelf --set-rpath` corrupted executables on mips32el: the dynamic
liker crushed with Segmentation fault when loading any executable with
RPATH added that way.

The problem was around the MIPS-specific mechanism of setting up the
debug map pointer. When DT_MIPS_RLD_MAP_REL entry in the dynamic section
is present, it holds the relative address of __RLD_MAP -- an offset
relative to this dynamic section entry. Dynamic linker puts the
pointer to the `r_debug` structure there.

When patchelf updates the executable RPATH, it moves the .dynamic
section both in the binary and in memory, while __RLD_MAP is not moved
in memory, since it belongs to special .rld_map section that has type
PROGBITS. So, the offset stored in DT_MIPS_RLD_MAP_REL entry is not
valid anymore and should be updated.

This commit adds the necessary update.

In the corner case when DT_MIPS_RLD_MAP_REL is present, but
.rld_map section is not, the dynamic loader writes the debug
pointer to some arbitrary bytes in memory. To avoid crushes
on otherwise "working" binaries, we set offset to zero
so that the dynamic loader would just overwrite the dynamic
section.

Here we also import DT_MIPS_RLD_MAP_REL definition in elf.h form
glibc commit a2057c984e4314c3740f04cf54e36c824e4c8f32.

Refs: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
haampie pushed a commit to haampie/patchelf that referenced this issue Nov 27, 2021
When loading the executable on MIPS, the dynamic loader looks for MIPS
ABI flags using PT_MIPS_ABIFLAGS header. The flags themselves are stored
in the .MIPS.abiflags section, so the header must be updated when the
section is moved.

Here we also import PT_MIPS_ABIFLAGS definition from glibc commit
0bd956720c457ff054325b48f26ac7c91cb060e8.

Closes: NixOS#82
Signed-off-by: Ivan A. Melnikov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants