NixOS / patchelf

A small utility to modify the dynamic linker and RPATH of ELF executables
GNU General Public License v3.0
3.48k stars 483 forks source link

Regression in 0.18.0: --set-rpath creates broken header alignment #528

Open mika-fischer opened 10 months ago

mika-fischer commented 10 months ago

Describe the bug

Using --set-rpath with 0.18.0 creates a broken header alignment. Using the patched library leads to error while loading shared libraries: libcudart.so.11.0: ELF load command address/offset not properly aligned. 0.17.2 works fine

Steps To Reproduce

patchelf-regression.zip

> cp libcudart.so.11.8.89.orig libcudart.so.11.8.89 && patchelf --set-rpath '$ORIGIN' libcudart.so.11.8.89
> readelf -Wl libcudart.so.11.8.89
[...]
Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
[...]
  LOAD           0x0a6000 0x0000000000400000 0x0000000000400000 0x003da0 0x003da0 RW  0x200000
[...]

Note that VirtAddr-Offset does is not aligned by Align

Expected behavior 0.17.2 produces

> readelf -Wl libcudart.so.11.8.89
[...]
Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
[...]
  LOAD           0x0a6000 0x00000000002a7000 0x00000000002a7000 0x003da0 0x003da0 RW  0x1000
[...]

Note that VirtAddr-Offset does is aligned by Align

patchelf --version output

patchelf 0.18.0

mika-fischer commented 10 months ago

Might be related to https://github.com/NixOS/patchelf/pull/475

petrmanek commented 9 months ago

I can see a very similar issue in the latest Ubuntu Focal with patchelf 0.18.0 compiled from source. It seems that a call to --set-rpath somehow corrupts the ELF binary to the point where ld.so no longer recognizes it as a dynamic executable. That being said, even though my symptoms fit the description above I am uncertain whether this is due to header alignment. I will try to confirm this and get back.

In the meantime, here is my minimal example that you can try e.g. in a Docker container:

cp /lib/x86_64-linux-gnu/libxcb-image.so.0 .

ldd libxcb-image.so.0
    linux-vdso.so.1 (0x00007ffcde5e9000)
    libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f1b1a17e000)
    libxcb-util.so.1 => /lib/x86_64-linux-gnu/libxcb-util.so.1 (0x00007f1b19f78000)
    libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f1b19f4e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1b19d5c000)
    libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f1b19d56000)
    libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f1b19d4e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f1b1a39b000)
    libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f1b19d32000)

patchelf --set-rpath \$ORIGIN libxcb-image.so.0

ldd libxcb-image.so.0
    not a dynamic executable

I am attaching a side-by-side diff of objdump -x of the patched ELF binary: diff_set_rpath.txt

RJVB commented 6 months ago

Still an issue with HEAD...