Skip to content

0.17.0: Segmentation fault after modifying RPATH #446

@bastimeyer

Description

@bastimeyer

Describe the bug

Just encountered an issue with patchelf 0.17.0...

I build AppImages for my Python application, and in order to do that I'm using Python's official manylinux docker images where I copy one of the pre-built python environments and modify the RPATHs of all binaries and their dependencies using patchelf. The RPATHs get set to $ORIGIN (and other relative paths), so that when the AppImage's squashfs gets mounted on the user's system upon execution, Python can properly be run on unknown/arbitrary mount points. So far, this has all been working flawlessly.

The patchelf 0.17.0 upgrade however has introduced segmentation faults of modified executables after modifying their RPATH. Patchelf 0.16.1 was working fine.

When looking at the recent git commit history, there was a big change in 2cb863f in regards to the ELF header file with lots of changed constants. I have 0% knowledge of any internals here and how ELF files and dynamic linking works, but that's what stood out to me.

Steps To Reproduce

Here's a short BASH script for reproducing the issue in two manylinux docker containers. One with patchelf 0.16.1 and the next one right after patchelf was upgraded to 0.17.0. There are other changes included between those two image versions, but those are unrelated and the issue can also be reproduced by simply building patchelf 0.17.0 on the older image.

#!/usr/bin/env bash

IMAGES=(
  # 2022-11-14 - patchelf 0.16.1
  quay.io/pypa/manylinux2014_x86_64@sha256:005826a6fa94c97bd31fccf637a0f10621304da447ca2ab3963c13991dffa013
  # 2022-11-19 - patchelf 0.17.0
  quay.io/pypa/manylinux2014_x86_64@sha256:383c6016156c94d7dbd10696c15f2444288b99a25927239b7b024e1cc6ca6a81
)

SCRIPT=$(cat <<'EOF'
PYTHON=/opt/python/cp310-cp310/bin/python

patchelf --version
$PYTHON --version

rpath=$(patchelf --print-rpath $PYTHON)
echo "RPATH: $rpath"

# Modify the python executable:
# set a different value, so the file actually gets written
patchelf --debug --set-rpath "\$ORIGIN" $PYTHON
echo "TEMP RPATH: $(patchelf --print-rpath $PYTHON)"

# and revert it again
patchelf --debug --set-rpath "$rpath" $PYTHON
echo "RPATH: $(patchelf --print-rpath $PYTHON)"

$PYTHON --version
EOF
)

for image in "${IMAGES[@]}"; do
  echo "Running ${image}"
  docker run -i --rm "${image}" <<< "${SCRIPT}"
  echo $'\n\n\n'
done

Log output

$ ./patchelf-bug.sh
Running quay.io/pypa/manylinux2014_x86_64@sha256:005826a6fa94c97bd31fccf637a0f10621304da447ca2ab3963c13991dffa013
patchelf 0.16.1
Python 3.10.8
RPATH: 
patching ELF file '/opt/python/cp310-cp310/bin/python'
new rpath is '$ORIGIN'
rpath is too long, resizing...
DT_NULL index is 30
replacing section '.dynamic' with size 592
replacing section '.dynstr' with size 36674
this is an executable
using replaced section '.dynstr'
using replaced section '.dynamic'
last replaced is 20
looking at section '.interp'
replacing section '.interp' 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 '.note.ABI-tag'
replacing section '.note.ABI-tag' which is in the way
looking at section '.gnu.hash'
replacing section '.gnu.hash' which is in the way
looking at section '.dynsym'
replacing section '.dynsym' which is in the way
looking at section '.dynstr'
looking at section '.gnu.version'
first reserved offset/addr is 0x17fea/0x417fea
first page is 0x400000
needed space is 98952
needed space is 99008
needed pages is 1
clearing first 101586 bytes
rewriting section '.dynamic' from offset 0x2ee288 (size 576) to offset 0x318 (size 592)
rewriting section '.dynstr' from offset 0xf0b0 (size 36666) to offset 0x568 (size 36674)
rewriting section '.dynsym' from offset 0x3500 (size 48048) to offset 0x94b0 (size 48048)
rewriting section '.gnu.hash' from offset 0x308 (size 12792) to offset 0x15060 (size 12792)
rewriting section '.interp' from offset 0x2a8 (size 28) to offset 0x18258 (size 28)
rewriting section '.note.ABI-tag' from offset 0x2e8 (size 32) to offset 0x18278 (size 32)
rewriting section '.note.gnu.build-id' from offset 0x2c4 (size 36) to offset 0x18298 (size 36)
rewriting symbol table section 3
writing /opt/python/cp310-cp310/bin/python
TEMP RPATH: $ORIGIN
patching ELF file '/opt/python/cp310-cp310/bin/python'
new rpath is ''
writing /opt/python/cp310-cp310/bin/python
RPATH: 
Python 3.10.8




Running quay.io/pypa/manylinux2014_x86_64@sha256:383c6016156c94d7dbd10696c15f2444288b99a25927239b7b024e1cc6ca6a81
patchelf 0.17.0
Python 3.10.8
RPATH: 
patching ELF file '/opt/python/cp310-cp310/bin/python'
new rpath is '$ORIGIN'
rpath is too long, resizing...
DT_NULL index is 30
replacing section '.dynamic' with size 592
replacing section '.dynstr' with size 36674
this is an executable
using replaced section '.dynstr'
using replaced section '.dynamic'
last replaced is 20
looking at section '.interp'
replacing section '.interp' 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 '.note.ABI-tag'
replacing section '.note.ABI-tag' which is in the way
looking at section '.gnu.hash'
replacing section '.gnu.hash' which is in the way
looking at section '.dynsym'
replacing section '.dynsym' which is in the way
looking at section '.dynstr'
looking at section '.gnu.version'
first reserved offset/addr is 0x17fea/0x417fea
first page is 0x400000
needed space is 98952
needed space is 99008
needed pages is 1
clearing first 101586 bytes
rewriting section '.interp' from offset 0x2a8 (size 28) to offset 0x318 (size 28)
rewriting section '.note.gnu.build-id' from offset 0x2c4 (size 36) to offset 0x338 (size 36)
rewriting section '.note.ABI-tag' from offset 0x2e8 (size 32) to offset 0x360 (size 32)
rewriting section '.gnu.hash' from offset 0x308 (size 12792) to offset 0x380 (size 12792)
rewriting section '.dynsym' from offset 0x3500 (size 48048) to offset 0x3578 (size 48048)
rewriting section '.dynstr' from offset 0xf0b0 (size 36666) to offset 0xf128 (size 36674)
rewriting section '.dynamic' from offset 0x2ee288 (size 576) to offset 0x18070 (size 592)
rewriting symbol table section 5
writing /opt/python/cp310-cp310/bin/python
TEMP RPATH: $ORIGIN
patching ELF file '/opt/python/cp310-cp310/bin/python'
new rpath is ''
writing /opt/python/cp310-cp310/bin/python
RPATH: 
/bin/bash: line 18:    14 Segmentation fault      (core dumped) $PYTHON --version

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions