termux-exec

repository·master·Indexed 42 days ago

https://github.com/termux/termux-exec-package

Utilities and shared libraries for the Termux execution environment that use $LD_PRELOAD to intercept the exec() family of functions. It enables the resolution of Linux bin paths to the Termux prefix and provides a system_linker_exec solution to bypass App Data File Execute restrictions on Android 10+.

Tokens
5.1K
Snippets
19
Records
31
Agent score
54%

What's inside termux-exec

  1. Overview of termux-exec-package

    master
    The termux-exec-package provides utilities and libraries for the Termux execution environment. Its primary purpose is to provide a shared library designed to be preloaded via the $LD_PRELOAD environment variable. This preloading ensures the proper functioning of the Termux execution environment by intercepting or augmenting execution behaviors.
  2. Use TERMUX_EXEC__PROC_SELF_EXE for path resolution

    master

    When system_linker_exec is active, /proc/pid/exe points to /system/bin/linker64 instead of the actual executable. To find the real path of the executable being run, software should use the TERMUX_EXEC__PROC_SELF_EXE environment variable.

    Warning: If you unset LD_PRELOAD in a current process, TERMUX_EXEC__PROC_SELF_EXE will not be automatically updated for subsequent nested exec() calls. You must manually unset it in the first nested process to prevent incorrect values from being passed down.

    # Example of preventing issues when unsetting LD_PRELOAD:
    system_linker_exec optional: LD_PRELOAD= $TERMUX__PREFIX/bin/sh -c 'echo $TERMUX_EXEC__PROC_SELF_EXE'; $TERMUX__PREFIX/bin/dash -c "echo \$TERMUX_EXEC__PROC_SELF_EXE"
    
    system_linker_exec mandatory: LD_PRELOAD= $TERMUX__PREFIX/bin/sh -c 'echo $TERMUX_EXEC__PROC_SELF_EXE'; /system/bin/linker64 $TERMUX__PREFIX/bin/dash -c "echo \$TERMUX_EXEC__PROC_SELF_EXE"
  3. How the termux-exec $LD_PRELOAD mechanism works

    master

    The termux-exec-package provides shared libraries designed to be preloaded via the $LD_PRELOAD environment variable. This mechanism ensures the proper functioning of the Termux execution environment by intercepting the exec() family of functions.

    There are two primary library variants provided:

    1. libtermux-exec-direct-ld-preload.so: Used for the direct execution type. It is the default variant and is designed to support system_linker_exec requirements during package updates.
    2. libtermux-exec-linker-ld-preload.so: Used for the system_linker_exec execution type. It intercepts additional functions to resolve issues specific to system_linker_exec without impacting the performance of users on the direct execution type.

    Automatic Setup: During package installation, a postinst script runs termux-exec-ld-preload-lib setup. This command checks if system_linker_exec is enabled (via termux-exec-system-linker-exec is-enabled) and copies the appropriate variant to $TERMUX__PREFIX/usr/lib/libtermux-exec-ld-preload.so. This path is then exported in the $LD_PRELOAD variable by the Termux login script.

  4. How termux-exec handles Linux vs Termux bin paths

    master

    Standard Linux software often assumes a root filesystem starting at / with binaries located in /bin or /usr/bin. On Android, these paths either do not exist or point to Android system binaries in /system/bin, rather than the Termux binaries located in $TERMUX__PREFIX/bin.

    termux-exec solves this by intercepting the exec() family of functions. When an execution is attempted using a path starting with /bin/ or /usr/bin/, or when a script's shebang points to such a path, termux-exec replaces the prefix with the Termux prefix path ($TERMUX__PREFIX/bin/).

    To enable this behavior, termux-exec must be set in the $LD_PRELOAD environment variable.

    Prefix Resolution Logic:

    1. It attempts to use the $TERMUX__PREFIX environment variable.
    2. If $TERMUX__PREFIX is not exported or is not a valid absolute path, it falls back to the default TERMUX__PREFIX value that was set during the termux-exec build time.
    export LD_PRELOAD=/path/to/libtermux-exec.so
  5. How `termux-exec` overrides the `exec()` family

    master

    The termux-exec package overrides the entire exec() family of functions (declared in unistd.h) to address specific execution restrictions in Termux.

    Important Limitations:

    • Direct System Calls: It does not override direct calls to the execve() system call made via syscall(2). Programs using direct system calls must be patched to use exec() wrappers or run under proot.
    • Static Binaries: Statically linked binaries (e.g., those produced by zig against musl) will not work with this interception mechanism.
    • Implementation: The interception is implemented via the $LD_PRELOAD library using ExecIntercept.c and ExecVariantsIntercept.c.
    /* Note: This is a conceptual description of the interception mechanism. */
    // termux-exec overrides the entire exec() family of functions,
    // but will not override direct calls to the execve() system call via syscall(2).
  6. Fix script shebangs using termux-fix-shebang

    master

    If you cannot use $LD_PRELOAD to intercept exec() calls, an alternative is to modify the script files directly. You can use termux-fix-shebang to update the interpreter path in a script's shebang line to point to the correct Termux path.

    This should be performed:

    • When a script is initially installed.
    • Whenever a script is written.
    • Whenever a script is upgraded.
    termux-fix-shebang <script_file>
  7. Follow Commit Message Guidelines

    master

    All commit messages must adhere to the Conventional Commits specification to enable automatic changelog generation.

    Formatting Rules:

    • The first letter of the type and description must be capitalized.
    • The description must be in the present tense.
    • A space after the colon : is mandatory.
    • For breaking changes, add an exclamation mark ! immediately before the colon : (e.g., Changed!: ...). This ensures the change is highlighted in the changelog.

    Structure:

    <type>[optional scope]: <description>
    
    [optional body]
    
    [optional footer(s)]
    <type>[optional scope]: <description>
    
    [optional body]
    
    [optional footer(s)]
  8. Enable termux-exec via LD_PRELOAD

    master

    The termux-exec package provides a shared library designed to be preloaded to ensure the proper functioning of the Termux execution environment. To enable it, export the LD_PRELOAD environment variable pointing to the libtermux-exec-ld-preload.so library located in your Termux prefix.

    Important Note on Shell Updates: Exporting LD_PRELOAD or updating the termux-exec library will not affect the current running shell. Libraries are only loaded when a process starts. To apply changes to LD_PRELOAD (including unsetting it), you must start a new nested shell using exec() (e.g., by running a new shell command within the current one).

    export LD_PRELOAD="$TERMUX__PREFIX/usr/lib/libtermux-exec-ld-preload.so"
  9. Bypass App Data File Execute Restrictions via System Linker Exec

    master

    On Android >= 10, SELinux policies prevent untrusted_app* domains from executing files located in app data directories (e.g., /data/data/<package_name>) due to W^X (Write XOR Execute) restrictions.

    To bypass this, you can use the system dynamic linker to execute the file. Because the kernel/SELinux sees the system_linker_exec context of the linker rather than the app_data_file context of your binary, execution is permitted.

    Executing an ELF Binary

    To execute a 64-bit ELF binary located in your app data directory:

    /system/bin/linker64 /data/data/com.foo/executable [args]

    Executing a Script

    To execute a script with a shebang (e.g., #!/path/to/interpreter):

    /system/bin/linker64 /path/to/interpreter /data/data/com.foo/script.sh [args]

    Note: This method requires Android 10 or higher.

    # Example: Executing an ELF binary via the system linker
    /system/bin/linker64 /data/data/com.foo/executable [args]
    
    # Example: Executing a script via the system linker
    /system/bin/linker64 /path/to/interpreter /data/data/com.foo/script.sh [args]
  10. Configure TERMUX_EXEC__EXECVE_CALL__INTERCEPT

    master

    Controls whether termux-exec intercepts execve() wrapper calls in the Android bionic libc library.

    When enable is set, Termux-specific logic runs to resolve execution issues for files in Termux before calling the execve() system call. If disable is set, the execve() system call is called directly without interception.

    TERMUX_EXEC__EXECVE_CALL__INTERCEPT: 
    - `disable` - Intercept `execve()` will be disabled.
    - `enable` - Intercept `execve()` will be enabled. (Default)