Skip to content

Commit dc28ec6

Browse files
committed
Fixes and cleanups
1 parent 56629c4 commit dc28ec6

11 files changed

+184
-114
lines changed

.clang-tidy

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Checks: '-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-valist.Uninitialized'
1+
Checks: '-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-valist.Uninitialized,-clang-diagnostic-tautological-pointer-compare'
22

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ jobs:
1313
- uses: actions/checkout@v4
1414
- uses: Homebrew/actions/setup-homebrew@master
1515
- run: brew install clang-format
16-
- run: make
17-
- run: make check
18-
- run: make unit-test
16+
- run: make CC=clang
17+
- run: make check CC=clang
18+
- run: make unit-test CC=clang
1919

2020
actionlint:
2121
runs-on: ubuntu-latest

Makefile

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
1+
CC ?= clang
12
TERMUX_BASE_DIR ?= /data/data/com.termux/files
2-
CFLAGS += -Wall -Wextra -Werror -Wshadow -O2 -fvisibility=hidden
3+
CFLAGS += -Wall -Wextra -Werror -Wshadow -fvisibility=hidden -std=c17 -Wno-error=tautological-pointer-compare
34
C_SOURCE := src/termux-exec.c src/exec-variants.c
45
CLANG_FORMAT := clang-format --sort-includes --style="{ColumnLimit: 120}" $(C_SOURCE)
56
CLANG_TIDY ?= clang-tidy
67

8+
ifeq ($(SANITIZE),1)
9+
CFLAGS += -O1 -g -fsanitize=address -fno-omit-frame-pointer
10+
else
11+
CFLAGS += -O2
12+
endif
13+
714
libtermux-exec.so: $(C_SOURCE)
815
$(CC) $(CFLAGS) $(LDFLAGS) $(C_SOURCE) -DTERMUX_PREFIX=\"$(TERMUX_PREFIX)\" -DTERMUX_BASE_DIR=\"$(TERMUX_BASE_DIR)\" -shared -fPIC -o libtermux-exec.so
916

1017
tests/fexecve: tests/fexecve.c
1118
$(CC) $(CFLAGS) -DTERMUX_BASE_DIR=\"$(TERMUX_BASE_DIR)\" $< -o $@
1219

20+
$(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0: tests/print-argv0.c
21+
$(CC) $(CFLAGS) $< -o $@
22+
1323
clean:
14-
rm -f libtermux-exec.so tests/*-actual test-binary
24+
rm -f libtermux-exec.so tests/*-actual test-binary $(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0
1525

1626
install: libtermux-exec.so
1727
install libtermux-exec.so $(DESTDIR)$(PREFIX)/lib/libtermux-exec.so
1828

1929
uninstall:
2030
rm -f $(DESTDIR)$(PREFIX)/lib/libtermux-exec.so
2131

22-
on-device-tests: libtermux-exec.so tests/fexecve
32+
on-device-tests:
33+
make clean
34+
ASAN_OPTIONS=symbolize=0,detect_leaks=0 make SANITIZE=1 on-device-tests-internal
35+
36+
on-device-tests-internal: libtermux-exec.so tests/fexecve $(TERMUX_BASE_DIR)/usr/bin/termux-exec-test-print-argv0
2337
@LD_PRELOAD=${CURDIR}/libtermux-exec.so ./run-tests.sh
2438

2539
format:
@@ -36,6 +50,6 @@ deb: libtermux-exec.so
3650
termux-create-package termux-exec-debug.json
3751

3852
unit-test: test-binary
39-
./test-binary
53+
ASAN_OPTIONS=symbolize=0 ./test-binary
4054

41-
.PHONY: deb clean install uninstall test format check-format test
55+
.PHONY: clean install uninstall on-device-tests on-device-tests-internal format check deb unit-test

README.md

+10-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# termux-exec
2-
A `execve()` wrapper to fix two problems with exec-ing files in Termux.
2+
A `execve(3)` (and exec family of functions) wrapper to fix two problems with exec-ing files in Termux.
33

44
# Problem 1: Cannot execute files not part of the APK
55
Android 10 started blocking executing files under the app data directory, as
@@ -14,7 +14,7 @@ While there is merit in that general principle, this prevents using Termux and A
1414
as a general computing device, where it should be possible for users to create executable
1515
scripts and binaries.
1616

17-
# Solution 1: Cannot execute files not part of the APK
17+
## Solution
1818
Create an `exec` interceptor using [LD_PRELOAD](https://en.wikipedia.org/wiki/DLL_injection#Approaches_on_Unix-like_systems),
1919
that instead of executing an ELF file directly, executes `/system/bin/linker64 /path/to/elf`.
2020
Explanation follows below.
@@ -62,11 +62,6 @@ We could also consider patching this exec interception into the build process of
6262
**NOTE**: The above example used `/system/bin/linker64` - on 32-bit systems, the corresponding
6363
path is `/system/bin/linker`.
6464

65-
**NOTE**: While this circumvents the technical restriction, it still might be considered
66-
violating [Google Play policy](https://support.google.com/googleplay/android-developer/answer/9888379).
67-
So this workaround is not guaranteed to enable Play store distribution of Termux - but it's
68-
worth an attempt, and regardless of Play store distribution, updating the targetSdk is necessary.
69-
7065
# Problem 2: Shebang paths
7166
A lot of Linux software is written with the assumption that `/bin/sh`, `/usr/bin/env`
7267
and similar file exists. This is not the case on Android where neither `/bin/` nor `/usr/`
@@ -75,19 +70,16 @@ exists.
7570
When building packages for Termux those hard-coded assumptions are patched away - but this
7671
does not help with installing scripts and programs from other sources than Termux packages.
7772

78-
# Solution 2: Shebang paths
73+
## Solution
7974
Create an `execve()` wrapper that rewrites calls to execute files under `/bin/` and `/usr/bin`
8075
into the matching Termux executables under `$PREFIX/bin/` and inject that into processes
8176
using `LD_PRELOAD`.
8277

83-
# How to install
84-
1. Install with `pkg install termux-exec`.
85-
2. Exit your current session and start a new one.
86-
3. From now on shebangs such as `/bin/sh` and `/usr/bin/env python` should work.
87-
88-
# Where is LD_PRELOAD set?
89-
The `$PREFIX/bin/login` program which is used to create new Termux sessions checks for
90-
`$PREFIX/lib/libtermux-exec.so` and if so sets up `LD_PRELOAD` before launching the login shell.
78+
# Usage in Termux
79+
This `termux-exec` package comes preinstalled as an essential package in Termux. Each time a
80+
process is spawned by the app, the `LD_PRELOAD=$PREFIX/lib/libtermux-exec.so` environment variable
81+
is setup by the Android app. This environment variable needs to be kept at all times when executing
82+
files inside Termux.
9183

92-
Soon, when making a switch to target Android 10+, this will be setup by the Termux app even before
93-
launching any process, as `LD_PRELOAD` will be necessary for anything non-system to execute.
84+
In the future the linker `--wrap` functionaliy might be used to avoid having to rely on `LD_PRELOAD`
85+
always being present.

src/exec-variants.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ __attribute__((visibility("default"))) int execvp(const char *name, char *const
3939
}
4040

4141
__attribute__((visibility("default"))) int execvpe(const char *name, char *const *argv, char *const *envp) {
42-
// if (name == NULL || *name == '\0') { errno = ENOENT; return -1; }
42+
if (name == NULL || *name == '\0') {
43+
errno = ENOENT;
44+
return -1;
45+
}
4346

4447
// If it's an absolute or relative path name, it's easy.
4548
if (strchr(name, '/') && execve(name, argv, envp) == -1) {

0 commit comments

Comments
 (0)