Skip to content

Commit df8a21c

Browse files
committed
Apply realpath(3) when hooking readlink("/proc/self/exe")
1 parent 9f701ad commit df8a21c

7 files changed

+68
-7
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ test-binary
88
tests/fexecve
99
tests/popen
1010
tests/system-uname
11+
tests/readlink-proc-self-exe

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ tests/popen: tests/popen.c
2727
tests/system-uname: tests/system-uname.c
2828
$(CC) $(CFLAGS) -DTERMUX_BASE_DIR=\"$(TERMUX_BASE_DIR)\" $< -o $@
2929

30+
tests/readlink-proc-self-exe: tests/readlink-proc-self-exe.c
31+
$(CC) $(CFLAGS) -DTERMUX_BASE_DIR=\"$(TERMUX_BASE_DIR)\" $< -o $@
32+
3033
$(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0: tests/print-argv0.c
3134
$(CC) $(CFLAGS) $< -o $@
3235

@@ -43,7 +46,7 @@ on-device-tests:
4346
make clean
4447
ASAN_OPTIONS=symbolize=0,detect_leaks=0 make on-device-tests-internal
4548

46-
on-device-tests-internal: libtermux-exec.so tests/fexecve tests/popen tests/system-uname $(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0
49+
on-device-tests-internal: libtermux-exec.so tests/fexecve tests/popen tests/system-uname tests/readlink-proc-self-exe $(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0
4750
@LD_PRELOAD=${CURDIR}/libtermux-exec.so ./run-tests.sh
4851

4952
format:

src/termux-readlink.c

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ __attribute__((visibility("default"))) ssize_t readlink(const char *restrict pat
1010
if (strcmp(pathname, "/proc/self/exe") == 0) {
1111
const char *termux_self_exe = getenv("TERMUX_EXEC__PROC_SELF_EXE");
1212
if (termux_self_exe) {
13+
char resolved_path_buf[PATH_MAX];
14+
char *resolved_path = realpath(termux_self_exe, resolved_path_buf);
15+
if (resolved_path) {
16+
termux_self_exe = resolved_path_buf;
17+
}
1318
size_t termux_self_exe_len = strlen(termux_self_exe);
1419
size_t bytes_to_copy = (termux_self_exe_len < bufsiz) ? termux_self_exe_len : bufsiz;
1520
memcpy(buf, termux_self_exe, bytes_to_copy);

tests/popen.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include <stdio.h>
22

33
int main() {
4-
FILE* file = popen("uname", "r");
5-
char buffer[101];
6-
fscanf(file, "%100s", buffer);
7-
pclose(file);
8-
printf("%s\n", buffer);
9-
return 0;
4+
FILE *file = popen("uname", "r");
5+
char buffer[101];
6+
fscanf(file, "%100s", buffer);
7+
pclose(file);
8+
printf("%s\n", buffer);
9+
return 0;
1010
}

tests/readlink-proc-self-exe.c

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#define _DEFAULT_SOURCE
2+
#include <linux/limits.h>
3+
#include <stdio.h>
4+
#include <unistd.h>
5+
6+
int main() {
7+
char buf[PATH_MAX + 1];
8+
9+
ssize_t res = readlink("/proc/self/exe", buf, PATH_MAX);
10+
if (res < 0) {
11+
perror("readlink()");
12+
return 1;
13+
}
14+
buf[res] = 0;
15+
printf("%s\n", buf);
16+
return 0;
17+
}
18+

tests/readlink-proc-self-exe.sh

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
TMPDIR=$(mktemp -d)
2+
3+
cp tests/readlink-proc-self-exe $TMPDIR
4+
5+
cd $TMPDIR
6+
7+
ACTUAL_PATH_TO_SELF=$(./readlink-proc-self-exe)
8+
EXPECTED_PATH_TO_SELF=$TMPDIR/readlink-proc-self-exe
9+
10+
if [ "$ACTUAL_PATH_TO_SELF" != "$EXPECTED_PATH_TO_SELF" ]; then
11+
echo "ERROR(1): Expected '$EXPECTED_PATH_TO_SELF', was '$ACTUAL_PATH_TO_SELF'"
12+
exit 1
13+
fi
14+
15+
ln -s readlink-proc-self-exe symlinked-binary
16+
ACTUAL_PATH_TO_SELF=$(./symlinked-binary)
17+
if [ "$ACTUAL_PATH_TO_SELF" != "$EXPECTED_PATH_TO_SELF" ]; then
18+
echo "ERROR(2): Expected '$EXPECTED_PATH_TO_SELF', was '$ACTUAL_PATH_TO_SELF'"
19+
exit 1
20+
fi
21+
22+
ln -s symlinked-binary nested-symlinked-binary
23+
ACTUAL_PATH_TO_SELF=$(./nested-symlinked-binary)
24+
if [ "$ACTUAL_PATH_TO_SELF" != "$EXPECTED_PATH_TO_SELF" ]; then
25+
echo "ERROR(3): Expected '$EXPECTED_PATH_TO_SELF', was '$ACTUAL_PATH_TO_SELF'"
26+
exit 1
27+
fi
28+
29+
cd - > /dev/null
30+
31+
rm -rf $TMPDIR
32+
33+
echo ok
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ok

0 commit comments

Comments
 (0)