Skip to content

Commit

Permalink
Added: Add site, docs and old changelog files under MIT license
Browse files Browse the repository at this point in the history
Related commit 24f60904
  • Loading branch information
agnostic-apollo committed Jan 6, 2025
1 parent 5b5a1c7 commit 9d534ca
Show file tree
Hide file tree
Showing 23 changed files with 1,257 additions and 81 deletions.
6 changes: 5 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ Files:
Comment:
The `termux-exec` repository is released under the `Apache-2.0` license, unless specified
differently in a file/directory or in any additional `Files` sections below.
License: [Apache-2.0](licenses/termux__termux-exec-package__Apache-2.0.md)
License: [Apache-2.0](licenses/termux__termux-exec-package__Aache-2.0.md)

Files:
site/*
License: [MIT](licenses/termux__termux-exec-package__MIT.md)
90 changes: 10 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,23 @@
# termux-exec
A `execve()` wrapper to fix two problems with exec-ing files in Termux.
# termux-exec-package

# Problem 1: Cannot execute files not part of the APK
Android 10 started blocking executing files under the app data directory, as
that is a [W^X](https://en.wikipedia.org/wiki/W%5EX) violation - files should be either
writeable or executable, but not both. Resources:
The [`termux-exec`](https://github.com/termux/termux-exec) package provides a shared library that is meant to be preloaded with [`LD_PRELOAD`](https://man7.org/linux/man-pages/man8/ld.so.8.html) for proper functioning of the Termux execution environment.

- [Google Android issue](https://issuetracker.google.com/issues/128554619)
- [Termux: No more exec from data folder on targetAPI >= Android Q](https://github.com/termux/termux-app/issues/1072)
- [Termux: Revisit the Android W^X problem](https://github.com/termux/termux-app/issues/2155)
### Contents

While there is merit in that general principle, this prevents using Termux and Android
as a general computing device, where it should be possible for users to create executable
scripts and binaries.
- [Project](#project)

# Solution 1: Cannot execute files not part of the APK
Create an `exec` interceptor using [LD_PRELOAD](https://en.wikipedia.org/wiki/DLL_injection#Approaches_on_Unix-like_systems),
that instead of executing an ELF file directly, executes `/system/bin/linker64 /path/to/elf`.
Explanation follows below.
---

On Linux, the kernel is normally responsible for loading both the executable and the
[dynamic linker](https://en.wikipedia.org/wiki/Dynamic_linker). The executable is invoked
by file path with the [execve system call](https://en.wikipedia.org/wiki/Exec_(system_call)).
The kernel loads the executable into the process, and looks for a `PT_INTERP` entry in
its [ELF program header table](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#Program_header)
of the file - this specifies the path to the dynamic linker (`/system/bin/linker64` for 64-bit Android).
 

There is another way to load the two ELF objects:
[since 2018](https://android.googlesource.com/platform/bionic/+/8f639a40966c630c64166d2657da3ee641303194)
the dynamic linker can be invoked directly with `exec`.
If passed the filename of an executable, the dynamic linker will load and run the executable itself.
So, instead of executing `path/to/mybinary`, it's possible to execute
`/system/bin/linker64 /absolute/path/to/mybinary` (the linker needs an absolute path).

This is what `termux-exec` does to circumvent the block on executing files in the data
directory - the kernel sees only `/system/bin/linker64` being executed.

This also means that we need to extract [shebangs](https://en.wikipedia.org/wiki/Shebang_(Unix)). So for example, a call to execute:

```sh
./path/to/myscript.sh <args>
```

where the script has a `#!/path/to/interpreter` shebang, is replaced with:
## Project

```sh
/system/bin/linker64 /path/to/interpreter ./path/to/myscript.sh <args>
```
**Check the `termux-exec` project info [here](site/pages/en/projects/index.md), including `docs` and `releases` info.**

Implications:
---

- It's important that `LD_PRELOAD` is kept - see e.g. [this change in sshd](https://github.com/termux/termux-packages/pull/18069).
We could also consider patching this exec interception into the build process of termux packages, so `LD_PRELOAD` would not be necessary for packages built by the termux-packages repository.

- The executable will be `/system/bin/linker64`. So some programs that inspects the executable name (on itself or other programs) using `/proc/${PID}/exec` or `/proc/${PID}/comm` (where `$(PID}` could be `self`, for the current process) needs to be changed to instead inspect `argv0` of the process instead. See [this llvm driver change](https://github.com/termux/termux-packages/pull/18074) and [this pgrep/pkill change](https://github.com/termux/termux-packages/pull/18075).

- Statically linked binaries will not work. These are rare in Android and Termux, but zig currently produces statically linked binaries against musl libc.

- The interception using `LD_PRELOAD` will only work for programs using the [C library wrappers](https://linux.die.net/man/3/execve) for executing a new process, not when using the `execve` system call directly. Luckily most programs do use this. Programs using raw system calls needs to be patched or be run under [proot](https://wiki.termux.com/wiki/PRoot).

**NOTE**: The above example used `/system/bin/linker64` - on 32-bit systems, the corresponding
path is `/system/bin/linker`.

**NOTE**: While this circumvents the technical restriction, it still might be considered
violating [Google Play policy](https://support.google.com/googleplay/android-developer/answer/9888379).
So this workaround is not guaranteed to enable Play store distribution of Termux - but it's
worth an attempt, and regardless of Play store distribution, updating the targetSdk is necessary.

# Problem 2: Shebang paths
A lot of Linux software is written with the assumption that `/bin/sh`, `/usr/bin/env`
and similar file exists. This is not the case on Android where neither `/bin/` nor `/usr/`
exists.

When building packages for Termux those hard-coded assumptions are patched away - but this
does not help with installing scripts and programs from other sources than Termux packages.

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

# How to install
1. Install with `pkg install termux-exec`.
2. Exit your current session and start a new one.
3. From now on shebangs such as `/bin/sh` and `/usr/bin/env python` should work.

# Where is LD_PRELOAD set?
The `$PREFIX/bin/login` program which is used to create new Termux sessions checks for
`$PREFIX/lib/libtermux-exec.so` and if so sets up `LD_PRELOAD` before launching the login shell.

Soon, when making a switch to target Android 10+, this will be setup by the Termux app even before
launching any process, as `LD_PRELOAD` will be necessary for anything non-system to execute.
&nbsp;
23 changes: 23 additions & 0 deletions licenses/termux__termux-exec-package__MIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
MIT License

Copyright (c) 2023 termux

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

- https://opensource.org/licenses/MIT
141 changes: 141 additions & 0 deletions site/pages/en/projects/docs/developer/build/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
page_ref: "@ARK_PROJECT__VARIANT@/termux/termux-exec-package/docs/@ARK_DOC__VERSION@/developer/build/index.md"
---

# termux-exec-package Build Docs

<!-- @ARK_DOCS__HEADER_PLACEHOLDER@ -->

The [`termux-exec`](https://github.com/termux/termux-exec) build instructions are available below. For install instructions, check [`install`](../../install/index.md) docs.

### Contents

- [Build Methods](#build-methods)

---

&nbsp;





## Build Methods

The `termux-exec` package provided by Termux is built from the [`termux/termux-exec`](https://github.com/termux/termux-exec) repository. It can be built with the following methods.

- [Termux Packages Build Infrastructure](#termux-packages-build-infrastructure)
- [On Device With `make`](#on-device-with-make)

**The [Termux Packages Build Infrastructure](#termux-packages-build-infrastructure) is the recommended way to build `termux-exec`.** If the `termux-exec` package is built with the [Termux Packages Build Infrastructure](#termux-packages-build-infrastructure), then the Termux variable values in the `Makefile` are dynamically set to the values defined in the [`properties.sh`] file of the build infrastructure by passing them to `make` via the `$TERMUX_PKG_EXTRA_MAKE_ARGS` variable set in the [`packages/termux-exec/build.sh`] file. If `termux-exec` is built with `make` instead, then the hardcoded fallback/default Termux variable values in the `Makefile` will get used during build time, which may affect or break `termux-exec` at runtime if current app/environment is different from the Termux default one (`TERMUX_APP__PACKAGE_NAME=com.termux` and `TERMUX__ROOTFS=/data/data/com.termux/files`). However, if `make` must be used for some reason, and building for a different app/environment than the Termux default, like for a Termux fork or alternate package name/rootfs, then manually update the hardcoded values in the `Makefile` or manually pass the alternate values to the `make` command.

## &nbsp;

&nbsp;



### Termux Packages Infrastructure

To build the `termux-exec` package with the [`termux-packages`](https://github.com/termux/termux-packages) build infrastructure, the provided [`build-package.sh`](https://github.com/termux/termux-packages/blob/master/build-package.sh) script can be used. Check the [Build environment](https://github.com/termux/termux-packages/wiki/Build-environment) and [Building packages](https://github.com/termux/termux-packages/wiki/Building-packages) docs for how to build packages.

#### Default Sources

To build the `termux-exec` package from its default repository release tag or git branch sources that are used for building the package provided in Termux repositories, just clone the `termux-packages` repository and build.

```shell
# Clone `termux-packages` repo and switch current working directory to it.
git clone https://github.com/termux/termux-packages.git
cd termux-packages

# (OPTIONAL) Run termux-packages docker container if running off-device.
./scripts/run-docker.sh

# Force build package and download dependencies from Termux packages repositories.
./build-package.sh -f -I termux-exec
```

#### Local Sources

To build the `termux-exec` package from its local sources or a pull request branch, clone the `termux-packages` repository, clone/create the `termux-exec` repository locally, make required changes to the [`packages/termux-exec/build.sh`] file to update the source url and then build.

Check [Build Local Package](https://github.com/termux/termux-packages/wiki/Building-packages#build-local-package) and [Package Build Local Source URLs](https://github.com/termux/termux-packages/wiki/Creating-new-package#package-build-local-source-urls) docs for more info on how to building packages from local sources.*

```shell
# Clone `termux-packages` repo and switch current working directory to it.
git clone https://github.com/termux/termux-packages.git
cd termux-packages

# Update `$TERMUX_PKG_SRCURL` variable in `packages/termux-exec/build.sh`.
# We use `file:///path/to/source/dir` format for the local source URL.
TERMUX_PKG_SRCURL=file:///home/builder/termux-packages/sources/termux-exec
TERMUX_PKG_SHA256=SKIP_CHECKSUM

# Clone/copy `termux-exec` repo at `termux-packages/sources/termux-exec`
# directory. Make sure current working directory is root directory of
# termux-packages repo when cloning.
git clone https://github.com/termux/termux-exec.git sources/termux-exec

# (OPTIONAL) Manually switch to different (pull) branch that exists on
# origin if required, or to the one defined in $TERMUX_PKG_GIT_BRANCH
# variable of build.sh file, as it will not be automatically checked out.
# By default, the repo default/current branch that's cloned
# will get built, which is usually `master` or `main`.
# Whatever is the current state of the source directory will
# be built as is, including any uncommitted changes to current
# branch.
(cd sources/termux-exec; git checkout <branch_name>)

# (OPTIONAL) Run termux-packages docker container if running off-device.
./scripts/run-docker.sh

# Force build package and download dependencies from Termux packages repositories.
./build-package.sh -f -I termux-exec
```

## &nbsp;

&nbsp;



### On Device With `make`

To build `termux-exec` package on the device inside the Termux app with [`make`](https://www.gnu.org/software/make), check below. Do not use a PC to build the package as PC architecture may be different from target device architecture and the `clang` compiler wouldn't have been patched like Termux provided one is so that built packages are compatible with Termux, like patches done for `DT_RUNPATH`.

```shell
# Install dependencies.
pkg install clang git make termux-create-package

# Clone/copy `termux-exec` repo at `termux-exec` directory and switch
# current working directory to it.
git clone https://github.com/termux/termux-exec.git termux-exec
cd termux-exec

# Whatever is the current state of the `termux-exec` directory will be built.
# If required, manually switch to different (pull) branch that exists on origin.
git checkout <branch_name>

# Remove any existing deb files in current directory.
rm -f termux-exec_*.deb

# Build deb file for the architecture of the host device/clang compiler.
make deb

# Install.
# We use shell * glob expansion to automatically select the deb file
# regardless of `_<version>_<arch>.deb` suffix, that's why existing
# deb files were deleted earlier in case any existed with the wrong version.
dpkg -i termux-exec_*.deb
```

---

&nbsp;





[`packages/termux-exec/build.sh`]: https://github.com/termux/termux-packages/blob/master/packages/termux-exec/build.sh
[`properties.sh`]: https://github.com/termux/termux-packages/blob/master/scripts/properties.sh
51 changes: 51 additions & 0 deletions site/pages/en/projects/docs/developer/contribute/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
page_ref: "@ARK_PROJECT__VARIANT@/termux/termux-exec-package/docs/@ARK_DOC__VERSION@/developer/contribute/index.md"
---

# termux-exec-package Contribute Docs

<!-- @ARK_DOCS__HEADER_PLACEHOLDER@ -->

These docs are meant for you if you want to contribute to the [`termux/termux-exec`](https://github.com/termux/termux-exec) repository.

### Contents

- [Commit Messages Guidelines](#commit-messages-guidelines)

---

&nbsp;





## Commit Messages Guidelines

Commit messages **must** use the [Conventional Commits](https://www.conventionalcommits.org) spec so that changelogs can be automatically generated when [releases](../../../releases/index.md) are made as per the [Keep a Changelog](https://github.com/olivierlacan/keep-a-changelog) spec by the [`create-conventional-changelog`](https://github.com/termux/create-conventional-changelog) script, check its repository for further details on the spec.

**The first letter for `type` and `description` must be capital and description should be in the present tense.** The space after the colon `:` is necessary. For a breaking change, add an exclamation mark `!` before the colon `:` as an indicator, and it will also cause the change to be automatically highlighted in the changelog.

```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```

**Only the `types` listed below must be used exactly as they are used in the changelog headings.** For example, `Added: Add foo`, `Added|Fixed: Add foo and fix bar`, `Changed!: Change baz as a breaking change`, etc. You can optionally add a scope as well, like `Fixed(docs): Fix some bug`. **Do not use anything else as type, like `add` instead of `Added`, or `chore`, etc.**

- **Added** for new additions or features.
- **Changed** for changes in existing functionality.
- **Deprecated** for soon-to-be removed features.
- **Fixed** for any bug fixes.
- **Removed** for now removed features.
- **Reverted** for changes that were reverted.
- **Patched** for patches done for specific builds.
- **Security** in case of vulnerabilities.
- **Release** for when a new release is made.

---

&nbsp;
19 changes: 19 additions & 0 deletions site/pages/en/projects/docs/developer/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
page_ref: "@ARK_PROJECT__VARIANT@/termux/termux-exec-package/docs/@ARK_DOC__VERSION@/developer/index.md"
---

# termux-exec-package Developer Docs

<!-- @ARK_DOCS__HEADER_PLACEHOLDER@ -->

These docs are meant for the developers, maintainers and contributors of the [`termux/termux-exec`](https://github.com/termux/termux-exec) repository and its forks.

### Contents

- [Build](build/index.md)
- [Test](test/index.md)
- [Contribute](contribute/index.md)

---

&nbsp;
Loading

0 comments on commit 9d534ca

Please sign in to comment.