[Bug dynamic-link/34360] New: Harden dynamic-loader resolution of $ORIGIN DST for setuid/setgid binaries
carlos at redhat dot com via Glibc-bugs <[email protected]> Mon, 06 Jul 2026 15:25:39 +0000
| Newsgroups | gmane.comp.lib.glibc.bugs |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://sourceware.org/bugzilla/show_bug.cgi?id=34360
Bug ID: 34360
Summary: Harden dynamic-loader resolution of $ORIGIN DST for
setuid/setgid binaries
Product: glibc
Version: 2.43
Status: NEW
Severity: normal
Priority: P2
Component: dynamic-link
Assignee: unassigned at sourceware dot org
Reporter: carlos at redhat dot com
Target Milestone: ---
glibc's handling of $ORIGIN for AT_SECURE processes is unsafe if the
rpath is something like "$ORIGIN/../../../usr/lib/x86_64-linux-gnu".
_dl_dst_substitute() attempts to filter $ORIGIN in the rpath using
is_trusted_path_normalize(), but while is_trusted_path_normalize()
checks that the normalized path is trusted, it does not use this
normalized path for the actual lookup; so it will allow a path like
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/libc.so.6", which is
unsafe if /tmp/a/b is concurrently replaced with a symlink to a
directory that is deeper in the filesystem hierarchy (because then
"/tmp/a/b/../../../" might not be the same as "/").
Here is a testcase to demonstrate this behavior:
/tmp/a/b$ cat rpathtest.c
#include <stdio.h>
#include <sys/auxv.h>
int main(void){
printf("AT_SECURE=%lu\n", getauxval(AT_SECURE));
}
/tmp/a/b$ gcc -Wl,-rpath,'$ORIGIN/../../../usr/lib/x86_64-linux-gnu'
-o rpathtest rpathtest.c
/tmp/a/b$ sudo cp /usr/bin/strace /usr/bin/strace_as_setuid
/tmp/a/b$ sudo chmod u+s /usr/bin/strace_as_setuid
/tmp/a/b$ /usr/bin/strace_as_setuid -e trace=file ./rpathtest
execve("./rpathtest", ["./rpathtest"], 0x7ffdf22f13c0 /* 79 vars */) = 0
readlinkat(AT_FDCWD, "/proc/self/exe", "/tmp/a/b/rpathtest", 4096) = 18
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD,
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libc.so.6",
O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD,
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/",
0x7ffd3da08ce0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD,
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libc.so.6",
O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD,
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/",
0x7ffd3da08ce0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD,
"/tmp/a/b/../../../usr/lib/x86_64-linux-gnu/libc.so.6",
O_RDONLY|O_CLOEXEC) = 3
AT_SECURE=1
+++ exited with 0 +++
/tmp/a/b$ sudo rm /usr/bin/strace_as_setuid
Reported-by: Jann Horn <[email protected]>
--
You are receiving this mail because:
You are on the CC list for the bug.