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
elf: expand $ORIGIN in RUNPATH/RPATH entries #17149
Conversation
0ebd9a8
to
f2b3166
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me so far! Will request a few more reviews here.
Library/Homebrew/os/linux/elf.rb
Outdated
local_paths = (path.patchelf_patcher.runpath || path.patchelf_patcher.rpath)&.split(":")&.map do |rp| | ||
# Expand instances of $ORIGIN in the R(UN)PATH | ||
rp.gsub "$ORIGIN", path.parent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local_paths = (path.patchelf_patcher.runpath || path.patchelf_patcher.rpath)&.split(":")&.map do |rp| | |
# Expand instances of $ORIGIN in the R(UN)PATH | |
rp.gsub "$ORIGIN", path.parent | |
local_paths = (path.patchelf_patcher.runpath || path.patchelf_patcher.rpath)&.split(":")&.map do |runpath| | |
runpath.gsub "$ORIGIN", path.parent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could move this #gsub
call into the local_paths&.each
block below, I think.
Also: I'm not sure if we want #gsub
, since $ORIGIN
is only replaced by the dynamic linker if it is the prefix of the path, IIUC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we want
#gsub
, since$ORIGIN
is only replaced by the dynamic linker if it is the prefix of the path, IIUC.
$ORIGIN
gets substituted even if it's not the prefix; check this. Or TL;DR: a quick example:
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ patchelf --print-rpath python3.12
/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/lib
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ ldd python3.12
linux-vdso.so.1 (0x00007fff28bb6000)
libpython3.12.so.1.0 => /home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/lib/libpython3.12.so.1.0 (0x00007b09b6838000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007b09b660c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007b09b6523000)
/home/linuxbrew/.linuxbrew/lib/ld.so => /lib64/ld-linux-x86-64.so.2 (0x00007b09b6eb9000)
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ patchelf --set-rpath '$ORIGIN/../lib' python3.12
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ ldd python3.12
linux-vdso.so.1 (0x00007ffcba9d2000)
libpython3.12.so.1.0 => /home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../lib/libpython3.12.so.1.0 (0x0000701941109000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000701940edd000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x0000701940df4000)
/home/linuxbrew/.linuxbrew/lib/ld.so => /lib64/ld-linux-x86-64.so.2 (0x000070194178a000)
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ patchelf --set-rpath '/usr/bin/../../$ORIGIN/../lib' python3.12
linuxbrew@9c46a48f740f:~/.linuxbrew/opt/python/bin$ ldd python3.12
linux-vdso.so.1 (0x00007ffc6119c000)
libpython3.12.so.1.0 => /usr/bin/../..//home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../lib/libpython3.12.so.1.0 (0x00007cd2a2506000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007cd2a22da000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007cd2a21f1000)
/home/linuxbrew/.linuxbrew/lib/ld.so => /lib64/ld-linux-x86-64.so.2 (0x00007cd2a2b8a000)
Also, as can be seen in the path expansion logic, two more such tokens exist: $PLATFORM
and $LIB
. See https://www.akkadia.org/drepper/dsohowto.pdf, page 40, paragraph "$ORIGIN
is not the only DST available...". Though, I think they are less commonly seen and can be followed up later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the expansion into the local_paths&.each
block that follows, and replaced #gsub
with just #sub
(and only matches $ORIGIN
from beginning of string for each path in the list).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, oops. Will switch it back to a gsub
for anywhere in the string (looks like multiple occurrences of $ORIGIN
are also accepted - can't imagine in what scenario such a case would occur, but not really harder for us to handle).
linuxbrew@ac7f2339ac92:~/.linuxbrew/opt/python/bin$ patchelf --set-rpath '$ORIGIN/../../../../../../..$ORIGIN/../lib' python3.12
linuxbrew@ac7f2339ac92:~/.linuxbrew/opt/python/bin$ ldd python3.12
libpython3.12.so.1.0 => /home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../../../../../../../home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../lib/libpython3.12.so.1.0 (0x0000004002849000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000004002ec4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00000040030ef000)
/home/linuxbrew/.linuxbrew/lib/ld.so => /lib64/ld-linux-x86-64.so.2 (0x0000004000000000)
linuxbrew@ac7f2339ac92:~/.linuxbrew/opt/python/bin$ file /home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../../../../../../../home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../lib/libpython3.12.so.1.0
/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../../../../../../../home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.12.3/bin/./../lib/libpython3.12.so.1.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=34400f728c92b58b1adf2df38f5c3693b3bdc38c, not stripped
f2b3166
to
1908f05
Compare
1908f05
to
e81cb9e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I think technically glibc algorithm is here: https://github.com/bminor/glibc/blob/41903cb6f460d62ba6dd2f4883116e2a624ee6f8/elf/dl-load.c#L182-L228 |
45f7b1e
to
8c979cc
Compare
Moved the logic out into a separate function (and module) to make testing it easier, especially with the corner cases that have been noted so far. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
8c979cc
to
4f125b4
Compare
4f125b4
to
6ee3483
Compare
brew style
with your changes locally?brew typecheck
with your changes locally?brew tests
with your changes locally?Follow-up to #17136. It's possible for
RPATH
orRUNPATH
to have entries that contain$ORIGIN
, which expands to the directory where the ELF object is located.We need to expand
$ORIGIN
and search for dependencies in paths containing$ORIGIN
, too.