termux / termux-app

Termux - a terminal emulator application for Android OS extendible by variety of packages.

Home Page:https://f-droid.org/en/packages/com.termux

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Revisit the Android W^X problem

iamahuman opened this issue · comments

Feature description
Termux should circumvent Play Store policy of restricting execution of arbitrary code from third parties, by imitating what Google Chrome does. Bundling packages into APKs is certainly not the way to go.

  1. Consult Firefox and Chrome as to how it executes external code (e.g. JavaScript) while still managing to comply with Play Store policy.
  2. Run user code in a sandbox (isolated_app?), emulating forbidden system calls as needed. (Note that we already do this with execve to handle #!/usr/bin/... shebangs).
    • Additional permissions to control system can be granted through some kind of broker, which user code can communicate to via IPC.
    • Don't rely exclusively on ptrace through; rather, approach the problem with a mix of ptrace+seccomp+recompilation.
  3. Circumvent W^X restriction by using a custom binary loader (instead of e.g. /system/bin/linker).

Reference implementation

N/A

Related

On the one hand, we need to think about how we can still give the sandboxed code access to storage files. /storage is implemented via FUSE (filesystem in userspace), so perhaps we can just steal some hints from there.

On the other hand, we can use this opportunity to explore support for containers and containerized applications (e.g. Docker, Flatpak, ...), possibly after figuring out how to resolve complications made by the SE Android policies.

Termux should circumvent Play Store policy of restricting execution of arbitrary code

We would definitely risk being suddenly removed from play store if we try to circumvent the policy, but as you said I guess it is theoretically possible to comply in the same way as browsers with javascript.

I think what we need is some people to feel strong enough about this "issue" to actually develop and experiment with possible solutions. The apk route has been shown to be possible, but needs much more work.

Alternative ideas are great, but an idea is not really worth anything before it is implemented (as business people like to say).
Leaving the issue open for discussion, but please understand that basically only xeffyr and fornwall has looked into android-11 support so far, and I doubt they would take the lead to implement new ideas now that we have a proof-of-concept of the apk solution.

Bundling packages into APKs is certainly not the way to go.

Yes and No! I studied the use of a boot loops concept and made good experiences. pkg will be preserved but the *.apk will be individualized/customized. Thus, target=29+ and sdcard access are no more problems.

I agree with @iamahuman .. @xeffyr If we just use proot to solve this, it may become easier.. but it has its own problems...

1- This is a known fact- performance issues...

2- Usual termux users love the fact that these packages are run directly under the android system.. That's why most users ask for packages natively that adjust without them with proot
The presence of proot would render having no difference between termux's packages and other proot distros

3- Any bugs or issues with proot upstream would also be an issue with Termux....

4- The Build script would have to be modified.. I don't know to what extent....

The best approach, I think would be to modify termux-exec, which currently is a wrapper only for shebangs around execv(). This would mean more work.. but has its benefits...
This would mean that termux-exec, after modification, would be included with termux-app, like the bootstrap packages.. but would be executed by the app , which then executes these packages....

@suhan-paradkar We have only 3 variants of resolving the issue:

  1. Leaving everything as-is and continuting with SDK 28.
  2. Packaging everything as "native libs" of APK. - Look branch android-10.
  3. Using a custom ELF loader: proot or something else.
  4. System emulation.

Variant 1 is current one, 3 - against Play Store policy.

This would mean that termux-exec, after modification, would be included with termux-app, like the bootstrap packages.. but would be executed by the app , which then executes these packages....

To do so you need to inject a LD_PRELOAD into Dalvik/ART startup. This is not possible and therefore you can't use shared library approach. It also works on function level and not the system call - will cause troubles with non-C/C++ programs.

You need a program which takes ELF executable, load its sections into memory and passes execution flow. A bare variant of proot. ptrace() there would be required anyway, to be able handle execve calls recursively.

The Build script would have to be modified.. I don't know to what extent....

What is that build script? It won't be hard to make Termux app build proot and bundle into APK.

If you are talking about package scripts, then there no issues at all. It even possible to get rid of most of our packages with proot, they won't be needed in case of use of normal distribution.


IMO, impact on user experience is inevitable. You can't keep quality, functionality, performance or application store availability on high level at same time. Even now this isn't possible, not saying about what will be after fixing execve issue. Solution shouldn't bring more problems than fixing. If there is something that can fix more Termux issues than just execve, you should consider it instead.

  1. Packaging everything as "native libs" of APK. - Look branch android-10.
  2. Using a custom ELF loader: proot or something else. - against Play Store policy.

@xeffyr I've a question: Is the existence of proot in the termux.apk (bootstrap*) already a violation of the Play Store Directive? The insert would only be done/used after the package update/install TERMUX_ANDROID10 or when proot-distro is used and Google should not be interested.
In my bootloop concept, the extension of the elf-splits (not everything) is also outside the control of Google. And the app version update does not change to $PREFIX.

What is that build script? It won't be hard to make Termux app build proot and bundle into APK.

Agree! My current build script support also: "1. Leaving everything as-is and continuting with SDK 28."

Is the existence of proot in the termux.apk (bootstrap*) already a violation of the Play Store Directive?

https://support.google.com/googleplay/android-developer/answer/9888379:

An app distributed via Google Play may not modify, replace, or update itself using any method other than
Google Play's update mechanism. Likewise, an app may not download executable code (e.g. dex, JAR, .so
files) from a source other than Google Play. This restriction does not apply to code that runs in a virtual
machine and has limited access to Android APIs (such as JavaScript in a webview or browser). 

Proot by itself doesn't violate anything. But it lets application to continue violate policy through downloadable packages. Yes, Termux already violates the policy and it doesn't matter whether proot is added or not. It still exists in Play Store, but there are risks.

Yes, Termux already violates the policy

OK - very juristic formulation. Thus, play store as a distributor no longer suitable for a developing app like termux, when Google does not change that. In the bootloop, after the first version are always local dev-*.apk used.
For 29+, only the question of whether this level has advantages over 28, on which one should not do without?

The only "advantage" is being able to submit updates to Play Store. Not so many. Termux works on Android 11 and even on 12 beta. That's expected, because Android currently preserves backwards compatibility. Problems will be only if with specific update Google decides to drop it.

commented

It's there any possibility to change target sdk version value at run time?

It's there any possibility to change target sdk version value at run time?

No, that's stored in AndroidManifest.xml and used as is since install time by android. Changing it would require rebuilding and reinstalling APK. However, apt and apk system should be selectable at install time if designed right.

commented

These solutions wouldn't have to overall reduce usability: for example, if binaries could be installed to sdcard storage, that would be a huge plus elsewhere.

Sorry for the dumb question but with the packaging everything into the apk does that mean it is no longer possible for users to compile and run programs? That would be unfortunate.

@Vixeliz PRoot can be used to workaround that but:

a. Any custom executable loader is technically against Play Store app publishing policy. - Matters only if we decide to continue Play Store updates.
b. PRoot does modifications to program execution flow, adds performance penalty and not stable on some devices.
c. It is unknown how exactly this (Android W^X) issue is going to be solved: we may choose a different solution, use other executable loader or not use it at all.

@xeffyr I see, if you were to try and get back on play store is it feasable to have two versions one with proot and one without? My main use case for termux is developing applications and im very worried it won't be possible going forward.

@xeffyr I see, if you were to try and get back on play store is it feasable to have two versions one with proot and one without? My main use case for termux is developing applications and im very worried it won't be possible going forward.

I don't think 2 termux versions with and without proot would be a good idea. because it needs to maintain one for non-proot-ed termux app for target level 29 (assuming in-APK's for example) and for proot-ed termux app it also needs to maintain existing package implementation which is apt and would probably need much maintenance so preferably one choice is a choice

I see well personally i am crossing my fingers for proot then.

In the android-10 branch, proot is part of the bootstrap (W^X violation) and all executables (ELF) outside the Termux-APK (with n=~/../../lib) are usable through the loader (TERMUX_ANDROID10) with the losses described above. Disadvantage of the branch is, that the well-known pkg administration was abolished and everything is in APK. I've studied an alternative that is based on the ELF transfer/split from $PREFIX to $n. This advances an APK build with variable bootstrap (loop) but pkg would stay as it is.

The more ELF in $n are, the more effective Termux works with API>28. I suspect PlayStore would not refuse the installation and many of the discord kids would never notice any difference as they work with proot-distro.
A bigger problem is the withdrawal of @fornwall (currently has other priorities), which was the only one to do/able the PlayStore updates. So it would have to be found a person with the necessary knowledge and time that can replace him or he returns.

I suppose withdrawing from Play Store has one big problem: funding.

Play Store is a just one of ways for funding and no one of maintainers except Fornwall shares it (both account & funding) anyway.

While Termux can dance for follow its policies for app publishing, there no guarantees that they would not be more strict in future. Relying on it for publishing in-APK bundled packages potentially creates a point of failure that is beyond our control: every submitted apk goes through moderation, there could be delays and chance that apk will be rejected for (un)known reason. This creates a possibility that something may become broken as publishing of specific dependency version failed.

As an user, I think the best approach is the current one: don't use play store for publishing the app. Other ways to overcome this issue seem to have too many disadvantages and in future Google could tighten PS policies even more. There are already too much problems caused by wrong choices made by Google on Android done on the assumption that users are stupid, or for the sake of privacy and security (when instead those should be in a compromise with usability and comfort). You get two advantages by don't publishing the app to PS:

  • app is used mainly by who wants really use it and at least is ok with learning HOW to do it, so you potentially get less management problems on GitHub, reviews, already reported issues, etc
  • you don't need to refactor the app in a way that may be frustrating for established users, at least until android isn't going to drop backwards compatibility

Feature description Termux should circumvent Play Store policy of restricting execution of arbitrary code from third parties, by imitating what Google Chrome does. Bundling packages into APKs is certainly not the way to go.

  1. Consult Firefox and Chrome as to how it executes external code (e.g. JavaScript) while still managing to comply with Play Store policy.

  2. Run user code in a sandbox (isolated_app?), emulating forbidden system calls as needed. (Note that we already do this with execve to handle #!/usr/bin/... shebangs).

    • Additional permissions to control system can be granted through some kind of broker, which user code can communicate to via IPC.
    • Don't rely exclusively on ptrace through; rather, approach the problem with a mix of ptrace+seccomp+recompilation.
  3. Circumvent W^X restriction by using a custom binary loader (instead of e.g. /system/bin/linker).

Reference implementation

N/A

Related

In regards to the first point, Google and Mozilla use JIT to run custom code in Chrome and Firefox, respectively, so that the emulated code is as fast as native code. That is why also Chrome and Firefox in iOS are basically Safari clones, because iOS apps are restricted from using JIT unless it is through Apple's WebKit (at least not until recently when Apple allowed using JIT through their sandbox in iOS 14.4 I think). I thought about this problem, and I believe a way to circumvent the current Termux issue, which is addressed in the first point by @iamahuman, is that we can use a software like QEMU static to emulate same CPU binaries on execution restricted drives such as /sdcard and now /data/data, on the cost of slow startup to binaries. At the very least, on long running binaries, it would be as fast as native combined applications since QEMU static (assuming it is compiled without using interpretation only) use JIT as well.

commented

Android's Write/Execute restriction is just intolerable. Same for unconditionally denying apps to read/write access to common locations... These our OUR DEVICES.

For me, Termux was a huge part of what made Android an actually tolerable platform, as opposed to the iOS Digital Prison. Now, Android is almost as bad as iOS when I threw away my iPhone 3GS and got a Samsung S III...

But where do we go from here?

Can we get back control by migrating to something like LineageOS or one of the other custom Android distributions?

Is Android bearable if we just focus on rooting and ignoring Google's irritating policies?

Besides rooting or installing a different distro, is there something else we can do?

Or is it game over for Termux and we need to move to something like Purism to actually re-assert control over my own device?

While I agree these problems are annoying I don't see any reason why android should be considered as bad as ios. And personally I still don't see much to rooting. Technically apps can still do what they did before for termux and the w^x issue the solution is being in some sort of container or virtualization or something yes this is slower but to be fair on our mobile devices w^x could be a security concern. As for file locations I'm assuming you mean scoped storage. If that's the case that's up to the apps to implement things like document providers if they use their own data directory for their files or in the case of file managers there is still the MANAGE_EXTERNAL_STORAGE permission. I have a feeling as long as chromebooks exist and consumers care about sideloading android won't be restricted to the point of not still being able to be used as a computer.

(Sorry for formatting I'm on mobile currently and not as my samsung dex setup)

commented

I agree these problems are annoying

That's exactly the beginning and the end of it.

Why do we have these devices? If the device you OWN is annoying, why waste our money on it?

What other choices do we have or what can we hack together?

be fair on our mobile devices w^x could be a security concern

That's exactly the point. If I know what software I'm running. It's my responsibility.

I don't see any reason why android should be considered as bad as ios

I'm saying that Android in 2022 is about as awful as iOS already was by 2012...

sort of container or virtualization or something yes this is slower but to be fair on our mobile devices

I want to use my terminal to control and script my device.

My feeling is that the Android trajectory is becoming clear. Maybe I'm wrong, but it seems' like their plan is to make an idiot proof OS, yet there will always be new idiots. I would like to figure out how to get out ahead of it, instead of finding out what else I CAN'T DO with my phone each an update is force installed.

Maybe another Termux user already has a solution.

I don't think just accept it is a solution.

I don't know how to respond to each problem on mobile however I'll number.

  1. their aren't many other choices for some people with devices that can't be rooted or even if they can may be missing features

  2. you are correct you can choose which software to run via apks however if an app could just install any executable without you knowing and run it that would be a problem which is what w^x prevents. So instead you are forced to run that code in a sandbox which in my opinion makes sense. They aren't preventing people from running what they want apks can still be installed without limitations

  3. it is no where near as bad we have so much more customizablity even without rooting. We can sideload apps which is huge compared to ios. For example I develop android applications on my phone with no problem.

  4. you should still be able to do that even if they use something like proot. And I don't think the trajectory is clear you have to remember google is working on built in desktop mode for android and they have chromebooks. I want to give Google the benefit of the doubt and say they are making these changes for legitimate security concerns which in my mind isn't an issue cause as of rn they aren't limiting what apps can do. I cannot personally think of an app that would cease to work with these changes as long as the devs worked to figure out a solution. Termux is a great example of that point. In fact UserLand is using the latest api level which is based off of termux and let's you run Linux distros.

At the very least, on long running binaries, it would be as fast as native combined applications since QEMU static (assuming it is compiled without using interpretation only) use JIT as well.

It won't be same fast. QEMU with jit is 10-20 times slower than host. Without JIT up to 50 times. QEMU package with JIT enabled is available in Termux. You can try running some OSes (system-mode) or binaries (user-mode).

QEMU "static" mode simply do not exist.

Android's Write/Execute restriction is just intolerable. Same for unconditionally denying apps to read/write access to common locations... These our OUR DEVICES.

For me, Termux was a huge part of what made Android an actually tolerable platform, as opposed to the iOS Digital Prison. Now, Android is almost as bad as iOS when I threw away my iPhone 3GS and got a Samsung S III...

Is Android bearable if we just focus on rooting and ignoring Google's irritating policies?

Could we stop discussions from being going political and be productive on the solution, right @erwin ? Reminding about locked #1072.

Android is not your product. If you disagree with OS developer decisions, start your own project. No one restricts you from running Linux software, just follow the f*cking development guidelines and avoid use of legacy/undocumented interfaces, your app will be ok in long term.


Current summary on the available solutions:

  • Bundling native executables inside the APK. - Good, but has impact on user experience from package management side.
  • Using proot for running executables, leaving everything else same. - Possible issues with Play Store policy. On user side there is performance and stability impact.
  • Custom executable loader. - This solution could be better than proot from performance & stability side. Though it needs some effort from our side to develop suitable ELF loader not depending on execve, if we won't use proot code base.
  • QEMU system mode. - Great possibilities (it would be separate OS with own kernel), but significant impact on user experience due to performance issues. This will also turn Termux into system emulator rather than terminal emulator for Android OS.
  • QEMU user mode. - In theory can be used as custom executable loader. On practice it is unknown how it would work as it seem to require working execve(). If it would work, issues same as proot. Doesn't support emulation of certain system calls.
  • Recompiling binaries to WASM. - Won'tfix.

In fact UserLand is using the latest api level which is based off of termux and let's you run Linux distros.

Is that variant is published on Play Store? I don't use UserLAnd, but if it really passed Play Store moderation with proot, then Termux can do same.

@xeffyr yes they are on the Google play store using proot and the api level was either 30 or 31 I don't recall exactly.

Yes. UserLAnd uses latest API and still on Google Play. but i don't know if the app will stay in Google Play indefinitely. last update of an app was probably October 2021

I have a quick question if termux ends up going the built in packages route would nodejs still work(assuming it was included) since it is an interpreter?

I have a quick question if termux ends up going the built in packages route would nodejs still work(assuming it was included) since it is an interpreter?

Assuming interpreter shells like bash, python and node are included in the apk, users would have to run bash script.sh, python script.py and node script.js. Direct execution like ./script.sh will not work.

solution with in apk embedding is very inconvenient.
a lot of apks in moderated play store, may be late updates, no dependency management, no user's own code and package file customization.
termux will lose a lot of it's power.
and play store admins will be able to block individual apps.
they may forbid to have hundreds of apks.

this is the only solution which is not a hack, but it is really ugly!

termux is already not updating in play store, and it is alive despite of this.
is it really nesasery to present in play store?

solution with in apk embedding is very inconvenient.

Agreed.

a lot of apks in moderated play store, may be late updates, no dependency management

Dependency management might be solveable. Late updates is not really a unique problem to the apk solution.

no user's own code and package file customization.

Stay on ~android 10 apps from fdroid if apk solution for google play doesn't fit your needs

and play store admins will be able to block individual apps. they may forbid to have hundreds of apks.

We'll probably go for bundles containing multiple packages instead of one apk per package.

termux is already not updating in play store, and it is alive despite of this. is it really nesasery to present in play store?

Not everyone can install apps from fdroid and similar, for example people using a company phone. And who knows, maybe from android 13 or 14 (or 15 or ..) termux as packaged for fdroid might not work at all. Having a working apk-solution would decrease the implication of that

Probably we will maintain both an android 7 - 9 app (at fdroid) and an android >= 10 app at google play for quite some time, if we ever get a somewhat working apk-based solution.

Probably we will maintain both an android 7 - 9 app (at fdroid) and an android >= 10 app at google play for quite some time, if we ever get a somewhat working apk-based solution.

That would mean more maintenance having a separate branches for pre and post-android q versions of Termux app. maybe we should stick the current solution right now at the moment, as long as it still works, who knows how far Termux would continue to work properly on newer android releases ¯\_(ツ)_/¯

That would mean more maintenance having a separate branches for pre and post-android q versions of Termux app

Yes, for sure.

maybe we should stick the current solution right now at the moment

Yeah, I think so too, but would be cool to have a small proof-of-concept app that mostly works, containing a (very) limited set of packages. It could then be released through github

Yeah, I think so too, but would be cool to have a small proof-of-concept app that mostly work ...

I would like that too! My (init) TargetSDK>=29 version contains p="proot aapt android-tools" and of course pkg. Thus, all subsequently installed packets can also be performed without bootloop at least with proot.

In the current Termux, is alias s='find $PREFIX -type f|wc -l' 3017 is after bootstrap+pkg up and with pkg in $p the result of s is 3318 on an Android-12 AVD (x86_64). So a basic-universal-TargetSDK=32 version would not be much larger than the current.

Addendum: to aapt and android-tools in $p and ELF-check

aapt (for APK analysis) is corrected agaib and android-tools I use only because of a bug in pm . If @agnostic-apollo has solved this as announced via env, only proot is necessary. The numbers above must be corrected with bootstrap *02.13-r1 and with s/ with $p/du -hd 0 ../usr are: 6588/6645/173M and *-r4 are: 3315/3322/88M .

ELF-Split/Check is based on an idea of ​​@xeffyr, but the @fornwall did not take over in its branches. In my bootloop this action takes place in Termux (u ec) to $PREFIX, requires the package zip (3335/89M) and after the bootstrap action is only one additional symlink: ln -s $PREFIX/nl $(realpath $nl) with nl=~/../../lib. Examle (u is an alias to script):

[~]$ s;u ec usr
3335
SYMLINKS.txt (2) check (update/##) start ...
finish with 0 old nl of 1099 ELF check start ...
327,1426 in 482 usr/(bin lib libex*)
update nl and libnl ...
-rwxr-xr-x 1 26M Jan  1  1981 /data/data/com.termux/lib/libtermux-bootstrap.so
-rw------- 1 37M Feb 14 15:13 bootstrap-x86_64.zip

Here (check) 327 files (47M) are identified, which would have to be included in SDK>28 in $nl. With parameter usr, this could be used to created boot*.zip for the next loop build (here init loop - needed 15 sec).
If TargetSDK=28 continue to be used, libnl can continue to stay in $PREFIX and the build needs 1-3 minutes depending on the PC power and number of arch. The entire process Inclusive installation can be done by script.

The debian package policy is quite complex and not designed for bundling files in APKs .. (next commit @agnostic-apollo)

I think you're right, but this is not relevant in boot-loop see small example of it below

That would mean more maintenance having a separate branches for pre and post-android q versions of Termux app.

There is no need for separate branches or even releases (other than optionally different targetSdkVersion for F-Droid and Play Store). If designed right, it can be managed in the same app/branch. User can be asked at install time for the method they want to use. Bootstrap/package installation is just a module for termux-app. Users on android 10+ who are rooted can also use legacy method if selinux policy is patched to disable exec restrictions. No need to force all android 10+ users to apk design.

#2445 (comment)

And apk design itself has issues for replicating apk updates and I am not really in support for it either, other than singular app without package updates for termux forks.

The debian package policy is quite complex and not designed for bundling files in APKs and symlinking them. Maintainer scripts (postinst, preinst, etc) are used by tonne of packages and they may fail with symlinks, considering simple checks like test -f will fail. So packages may need to be continuously manually reviewed by maintainers which is not really possible with the amount of maintainers we have. Package source code may not be expecting symlinks either, so those may need to be reviewed too, with patches added. Conffiles (like sshd_config) is another thing handled while installing with apt with a keep maintainer version or local version prompt. That will also have to be replicated in android app source code somehow. Other config files exist in deb too. There are likely other issues as well, in addition to the ones already mentioned above. As far as I know, mass testing of apk design with random packages has not been done either by anyone, so there are likely issues that we are not seeing yet. Replicating apt which has been developed over multiple decades in an android app is bound to have problems, if at all possible easily, specially with time constraints for maintainers. Even the current updated-flavor branch requires lot of work, its not doing everything correctly, although understandable, since its a POC.

Keep buying devices that can be bootloader unlocked/rooted would be my recommendations for power users who want to remain safe from future android restrictions. Android 12 already broke termux (#2366) and user friendly and safe fix won't be available to users until Android 12L or 13, if their devices even gets the update. Who knows what changes are made in future and if they would even be solvable without root by termux or not, especially in regards to how android is going hard against background execution since last few versions. APK packaging and other solutions won't solve such restrictions.

the problem globally may be solved by the following way:
add an other flag to disable this restriction to the manifest specification.
this flag may require special play store moderation.
the most apps will be restricted but some apps may be allowed.

why not ask about this on the official android resources?

it is very unlikely that it will be satisfied but why don't try?

a-Shell on iOS is been accepted on the Appstore: https://holzschu.github.io/a-Shell_iOS/, and for running custom binaries, the clang toolchain that comes with it compiles to web assembly and JIT run it using WASM3. I personally believe that for termux to be back on the store and have an efficient solution, while still maintaining the usability of the original termux, is to create a JIT launcher for custom binaries like JVM for Java classes, for instance, or WASM3, so it runs in near native speed. Just my two cents. Bundling executables, while allowing for running at full speed, it will be a huge inconvenience for the user to have to install APKs so they can run their binaries.

a-Shell on iOS is been accepted on the Appstore: https://holzschu.github.io/a-Shell_iOS/, and for running custom binaries, the clang toolchain that comes with it compiles to web assembly and JIT run it using WASM3. I personally believe that for termux to be back on the store and have an efficient solution, while still maintaining the usability of the original termux, is to create a JIT launcher for custom binaries like JVM for Java classes, for instance, or WASM3, so it runs in near native speed. Just my two cents. Bundling executables, while allowing for running at full speed, it will be a huge inconvenience for the user to have to install APKs so they can run their binaries.

That's interesting, to me it seems more future proof then proot but we will see the tradeoffs for maintenance and such between the options proposed so far. But honestly personally I would love to see wasm used I feel like it honestly might be a really good solution but that's just my two cents.

a-Shell on iOS is been accepted on the Appstore: https://holzschu.github.io/a-Shell_iOS/, and for running custom binaries, the clang toolchain that comes with it compiles to web assembly and JIT run it using WASM3. I personally believe that for termux to be back on the store and have an efficient solution, while still maintaining the usability of the original termux, is to create a JIT launcher for custom binaries like JVM for Java classes, for instance, or WASM3, so it runs in near native speed. Just my two cents. Bundling executables, while allowing for running at full speed, it will be a huge inconvenience for the user to have to install APKs so they can run their binaries.

That's interesting, to me it seems more future proof then proot but we will see the tradeoffs for maintenance and such between the options proposed so far. But honestly personally I would love to see wasm used I feel like it honestly might be a really good solution but that's just my two cents.

Yes, WASM is th future. If Apple allows such app to be on the Appstore, I highly doubt Google is stricter than Apple, if not otherwise, and therefore we can ship Termux that comes bundled with wasm launcher.

There is no need for separate branches ... APK packaging and won't solve such other solutions restrictions.

@agnostic-apollo With everything I agree here, except with other solutions and:

As far as I know, mass testing of apk design with random packages has not been done either by anyone

I have successfully managed with my boot-loop method package collections of almost 100T files ($PREFIX>2Gb) and ELF-split in APK. Since you do not want to support the build with local bootstraps in master, I've put aside the investigations some time ago - there is currently no need.

That is why also Chrome and Firefox in iOS are basically Safari clones, because iOS apps are restricted from using JIT unless it is through Apple's WebKit (at least not until recently when Apple allowed using JIT through their sandbox in iOS 14.4 I think).

@falhumai96 This is how iSH managed to get through App Store. It doesn't use direct unsigned code execution, which Apple also doesn't allow, instead it emulates x86 usermode and syscalls, and it emulates it with a unique way:

It's not actually a JIT since it doesn't target machine code. Instead it generates an array of pointers to functions called gadgets, and each gadget ends with a tailcall to the next function; like the threaded code technique used by some Forth interpreters. The result is a speedup of roughly 3-5x compared to pure emulation.
— iSH GitHub Readme

This emulation makes it both as fast as JIT and able to be accepted to App Store.

Since Google doesn't really disallow JIT (their Chrome app themselves use JIT), maybe we can use iSH's approach, but with actual JIT (or maybe even AOT)

Seems to have required lot of changes to the handful of packages it supplies, at least for ios. Termux provides 1000s of packages, would require tonne of patches.

https://github.com/holzschu/ios_system

We have the limitations of WebAssembly: no sockets, no forks, no interactive user input (piping input from other commands with command | wasm program.wasm works fine).

https://github.com/holzschu/a-Shell#programming--add-more-commands

make sure your code doesn't use commands that don't work in a sandbox: fork, exec, system, popen, isExecutableFileAtPath, access... (some of these fail at compile time, others fail silently at run time).

https://github.com/holzschu/ios_system/#adding-more-commands

Not sure how something like that would be usable for any reasonable termux or terminal usage.

p.s I don't have any experience with WASM.

You know what, UserLAnd app is currently working on supporting Android 10 and above using PRoot inside lib folder: CypherpunkArmory/UserLAnd#827. It is also currently in available in PlayStore with the update, and Google did not pull it out because of the PRoot support (I reckon Termux won't be pulled out too with PRoot support). I am with continuing further to PRoot, since PRoot internally is just a JIT using QEMU user mode, without too much penalty on performance.

Another slight suggestion is to merge the Termux project with UserLAnd, and make Termux Just an alternative shell inside UserLAnd, since really Termux will be just another shell running inside PRoot, but this one on another app (that's if Termux don't merge with UserLAnd). This is just my opinion.

You know what, UserLAnd app is currently working on supporting Android 10 and above using PRoot inside lib folder: CypherpunkArmory/UserLAnd#827. It is also currently in available in PlayStore with the update, and Google did not pull it out because of the PRoot support (I reckon Termux won't be pulled out too with PRoot support). I am with continuing further to PRoot, since PRoot internally is just a JIT using QEMU user mode, without too much penalty on performance.

Another slight suggestion is to merge the Termux project with UserLAnd, and make Termux Just an alternative shell inside UserLAnd, since really Termux will be just another shell running inside PRoot, but this one on another app (that's if Termux don't merge with UserLAnd). This is just my opinion.

The update to Android Q wasn't as smooth on UserLAnd's side. Reading/writing data from/to /sdcard is now a bit more inconvenient. This is the message you get when you run the app:
Screenshot_20220211-135208

Example continued of a "boot loop": In March 2021 I made the last ELF check on my SM-P610 (315 EFL files), in between several pkg * actions made and have currently 38549/1.4GB for $PREFIX. If I repeat now u ec, remain unchanged from the ELF files 58 (e.g., zip, Xwayland). The boot*.zip at 540MB would have to incorporate as the minimum version above in the build of the next version.
If the package set for all arch would be used the APK>2GB and even with a single arch are the installed data before the Init bootstrap action (2x*.zip) from Termux>1GB and after >2.5GB. with a correspondingly long installation duration.
I would prefer another process where prefix is ​​preserved if it still exists and only nl->libnl is replaced, that's only 203MB. If then the currently double storage of these boot data would be reduced to one, TERMUX would need less storage than now.

When I first met Termux (v0.73) it took about 200KB. Bootstrap was made like pkg via the servers, and has been predominantly installed by the Play Store. As far as storage efficiency is concerned, you should take this as a _model. Even the last Play Store version (v0.101) contains bootstrap only once and only thedevice arch. That's before/after bootstrap 19/82MB. The opposite is the current (v0.118) minimum requires 216MB at Universal (all arch) and currently only 5MB more in the bootstrap.

Waht do the new virtualisation capabilitiess in Android 13 mean to Termux? Would it be a solution for these problems?

Waht do the new virtualisation capabilitiess in Android 13 mean to Termux? Would it be a solution for these problems?

No. From what I know native KVM requires root

Yeah, direct KVM access requires root and likely won't change. If one has root, might as well patch the sepolicy to disable no exec restrictions.

https://twitter.com/topjohnwu/status/1492797907291967489

And sharedUserId will probably be phased out in some future release as well, so (rejoice) APK solution will likely not be used. Some plugins may need to be merged in termux-app as well if necessary. Android 13 android core package is still using sharedUserId but due to introduction of sharedUserMaxSdkVersion, it's likely that removal is now planned from its current deprecation status. So can't really invest resources if it's not gonna work in future. Termux did run on Android 13 DP1 in avd. I need to do some research and then ask google for their plans and possible solutions.

https://commonsware.com/blog/2022/02/12/random-musings-android-13-dp1.html#what-else-might-break-your-apps-in-the-not-too-distant-future

While this may not be the solution that you may look for
But I thought what if we bundle "android-tools" package with termux and execute termux binary with shell aka uid 2000
But adb shell environment differs from termux environment, so here is what I did.
1- I copied everything from /data/data/com.termux/ to /data/local/tmp
2- I also copied the libraries [libtermux.so] and [libtermux-bootstrap.so]
3- I checked files ownership and then i chmod 777 the files.
4- set up the environment variables

export PREFIX=/data/local/tmp/files/usr
export LD_LIBRARY_PATH=$PREFIX/lib
export PATH=$PREFIX/bin:$PATH

5- I could execute some binaries like ls and pwd but for the login and top binaries I get permission denied error
Now I know what are you thinking, and you are suspecting SELinux, but you will be mistaken to think so.
And even if I disable SELinux completely, I still get permission denied error when executing top binary.
I am very much sure that even with the latest version of android, shell aka user 2000 can still execute whatever it wants in /data/local/tmp
And I know that some of you may not like this way Because it will throw android 10 users under the bus
But all I want is to know why I am getting a permission denied error and how to fix it.

You need to recompile all packages with new /data/local/tmp/files/usr prefix and then then check.

https://github.com/termux/termux-packages/wiki/For-maintainers#build-bootstrap-archives

You will also need to build termux-app with the prefix changes for login shell, etc.

https://github.com/termux/termux-packages/blob/master/packages/termux-tools/login

Moreover, adb shell user will not be able to access any files under /data/data/com.termux and termux app itself will not be able to access any files under /data/local/tmp, so stuff like SAF and file sharing will break.

The shell user will also be limited to permissions declared in its manifest by android OS build, which may vary depending on android version.

https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/Shell/AndroidManifest.xml

You need to recompile all packages with new /data/local/tmp/files/usr prefix and then then check.

So you are telling me that the path is hard-coded into the binary regardless of the environment variables ?

https://github.com/termux/termux-packages/wiki/For-maintainers#build-bootstrap-archives

I looked into the link, but I did not find the specific line that I should change. More instruction would be nice.

You will also need to build termux-app with the prefix changes for login shell, etc.
https://github.com/termux/termux-packages/blob/master/packages/termux-tools/login

I looked into it, but it seems to reference PREFIX which is declared in the environment variables. But line 16 interest me. Maybe I should declare ~ home in the environment variables.

Moreover, adb shell user will not be able to access any files under /data/data/com.termux and termux app itself will not be able to access any files under /data/local/tmp, so stuff like SAF and file sharing will break.

That is true, and I completely agree with you on this one. Maybe we can use

/storage/emulated/0/
OR
/storage/emulated/0/Android/data/com.termux
they are both are accessible to app and shell

The shell user will also be limited to permissions declared in its manifest by android OS build, which may vary depending on android version.

I don't expect google to change shell capability to execute binaries any time soon. plus shell will always have more permissions and capabilities than a third party app. And most termux users using it as a third party app unless they have root.

Such a shame. I was hoping I was hoping able to run htop on my non rooted android 12 phone. And see a list of all the running process. But since android 7 no third party app can access the proc directory. But shell can still access the proc directory.

But you gotta admit. running htop on a non-rooted phone is cool or is it just me

But I guess I was hoping for the impossible. Because I don't love to maintain a fork of termux and re-compile it for every update.

And see a list of all the running process.

ps, pstree, top with different options show all running termux and plugin prozesses.

You need to recompile all packages with new /data/local/tmp/files/usr prefix and then then check.

So you are telling me that the path is hard-coded into the binary regardless of the environment variables ?

For the record this was discussed in termux/termux-packages#2902. Patching all packages to use a dynamic prefix would mean a lot of work, and lots of maintenance work as packages are updated.

So you are telling me that the path is hard-coded into the binary regardless of the environment variables ?

Yes, env variable is just a shortcut for scripts usage.

I looked into the link, but I did not find the specific line that I should change. More instruction would be nice.

It already says following. I have added link to file.

The package name/prefix that the bootstrap is built for is defined by TERMUX_APP_PACKAGE in scripts/properties.sh.

Maybe we can use

/storage/emulated/0/ OR /storage/emulated/0/Android/data/com.termux they are both are accessible to app and shell

External storage is mounted as noexec and does not allow execution of binaries.

I was hoping I was hoping able to run htop on my non rooted android 12 phone.

/system/bin already comes with ps and top to view processes.

https://android.googlesource.com/platform/system/core/+/master/shell_and_utilities/README.md

If you want htop, compile htop package with custom prefix, extract it in /data/local/tmp and run it with adb from android-tools, should hopefully work.

https://github.com/termux/termux-packages/wiki/Building-packages

shell is allowed sepolicy exemptions for /proc access.

https://cs.android.com/android/platform/superproject/+/android-12.0.0_r4:system/sepolicy/public/shell.te;l=102

External storage is mounted as noexec and does not allow execution of binaries

When I suggested /storage/emulated/0/ OR /storage/emulated/0/Android/data/com.termux I meant as medium to transfer files. And yes, while we can not execute files in these locations, we can copy it to a path when we can execute files.

And on the topic of google play. Google is going to remove the deprecated version of termux for us.
https://www.xda-developers.com/google-play-store-outdated-apps-policy/

While i understand the developers concern about google maintaining old API compatibility, I don't think google is going to drop API 28 compatibility anytime soon
take Google Chrome for example

Chrome 43.0.2357 (2015) No longer supports Android 4.
Chrome 72.0.3626 (2019) No longer supports Android 4.1-4.3
Chrome 83.0.4103 (2020) No longer supports Android 4.4

so far, the minimum API is 23 and even if you install API 17 for example, it will only give a useless warning asking the developer to update the app.

So if google really starts deprecating API 23 by year 2025
termux will still be alive until 2030, which is a lot of time from now.

I can't solve the technical problems but I do want to speak up for API 29+ having the following benefit: real file paths to USB storage.

For what it's worth I say forget about Play Store policy and only deal with Android restrictions. But I'm just some guy you know?

So, it looks like the "each package is its own APK" approach is dead on arrival, due to the deprecation (and likely eventual removal of) sharedUserId, as per #2155 (comment). (And, as many other users have pointed out, this approach was a major UX regression anyway.)

The only alternative to using sharedUserId I've seen is here and it sounds like absolute hell:

If the apk uses the same signing key and enables shared uid, data can be shared across them so there can be cross-app dependencies for executables/libraries. If they don't, then the only way for them to communicate and share data is via IPC started via intents. They can have streams open between each other but it wouldn't be possible for an executable to depend on a library or data in another apk. It would be possible to make a protocol for apps to expose CLI utility arguments and pipes via intents with scripting to make it work within the shell. It's a lot more convenient to use the same signature / shared uid so that data can simply be shared as if it's a single app consisting of multiple components.

I don't like this "solution" either:

Keep buying devices that can be bootloader unlocked/rooted would be my recommendations for power users who want to remain safe from future android restrictions.

You shouldn't have to sacrifice all the benefits of Android's security model just to use a shell on your phone.

Personally I don't think Termux should care about whether or not it's allowed to distribute through the Play Store. I think we should keep in mind that this app is a developer tool, and should only be used by those who know what they're doing with it (which means they should at least know how to install apps from outside the Play Store). It also reduces support burden on Termux maintainers as mentioned in #2155 (comment).

So for now I think sticking with API 28 is the right way to go, but that might not viable in the long-term, as others have warned of. AOSP (not just Google Play) already has a concept of "minimum API version", as detailed here. As of now all it does is show a warning that the application may not work properly, but they may eventually change it to where it refuses to launch the app at all. Additionally, it's not great to be stuck at an old API level because there are legitimate improvements (not just deprecations and restrictions), as #2155 (comment) pointed out.

As far as a long-term solution: I'm wondering if anyone has asked the Android team if they'd be willing to add a permission to bypass the W^X restriction on execve() and any future restrictions on executing downloaded code they may eventually add? I understand the concerns raised by Daniel Micay here:

That model doesn't work, even for experienced power users and developers. Apps are in a position to coerce users into accepting permissions. They choose not to implement fallbacks. For example, an app could respond to being denied the Contacts permission by using the API for having the user pick contacts to provide to the app which requires no permission. Are you aware of any app doing that? The same goes for storage access and camera access. They could ask for what they want and then fall back to a working implementation without a bulk data access permission. However, they don't, as they know users have to say yes to get done what they want to get done.

I agree and I think a runtime permission for executing external code would be extremely confusing for users, and apps could just pressure the user into granting it (since most users won't even understand what it's asking to do), defeating the purpose of the security feature.

However, there is another type of permission that I don't think anyone has brought up yet: development permissions. As described here:

Additional flag from base permission type: this permission can also (optionally) be granted to development applications.

These permissions can't be granted during runtime, nor even through the Settings UI. The only way for the user to grant them to apps is to use the pm command through the adb shell. The pm grant command internally calls PermissionManagerService.grantRuntimePermission(), and here we can see that there are only two types of permissions that are user-changeable: runtime and development (not including appops permissions, which are managed separately and used for "special app access" like "all files" and "install unknown apps").

Many of these development permissions are listed here. We can get the full list of development permissions as of Android 13 like so:

curl -s 'https://android.googlesource.com/platform/frameworks/base/+/android-13.0.0_r24/core/res/AndroidManifest.xml?format=TEXT' | base64 --decode | grep -C 5 'android:protectionLevel=".*development'

There are currently 26. Key Mapper is an example of an app that uses WRITE_SECURE_SETTINGS for some of its optional features. The process for granting the permission is described in their documentation. Tasker is another example.

Perhaps Google could add a development permission that allows bypassing W^X, i.e. something like EXECUTE_UNVERIFIED_CODE. Usage would be something akin to:

adb shell pm grant com.termux android.permission.EXECUTE_UNVERIFIED_CODE

Apps can't trick users into granting these permissions because the requirements for enabling them are sufficient to keep inexperienced users away:

  1. Enable developer options in settings
  2. Enable USB debugging
  3. Install the SDK platform tools on a separate computer
  4. Connect phone to computer and accept the USB debugging connection
  5. Run the adb shell command

Besides, the theoretical EXECUTE_UNVERIFIED_CODE permission is considerably less dangerous than the currently available development permissions (e.g. WRITE_SECURE_SETTINGS, READ_LOGS, etc). If it were possible to trick users into granting these permissions, there would be a much bigger problem here.

According to Micay,

It wasn't a change to protect the system from apps, but rather to make apps themselves harder to exploit.

If this is indeed true, then implementing the EXECUTE_UNVERIFIED_CODE permission as described will not introduce any security issues. Badly-designed apps that needlessly download and run native code from some server (probably via an unencrypted connection and without any signature/integrity verification) are no longer allowed on the platform, but developer tools like Termux that absolutely need this ability to provide their core functionality are still supported (albeit in a slightly roundabout way). As a final barrier preventing badly-designed apps from using this permission, Google could ban apps that request it from the Play Store altogether.

The fact that there still exist many ways to bypass Android's filesystem W^X would seem to support this claim. The recent changes make it difficult enough to dissuade app developers from doing it, while still allowing things like JIT for web browsers.

I understand that requiring users to run an adb shell command in order to use Termux is not ideal, but I think this would provide the best balance of usability and security (assuming we could ever convince Google to implement the permission). Plus, due to phantom process killing introduced in Android 12 for apps of all API levels, you already have to run an adb shell command to make Termux work properly on recent versions of Android. Similarly to settings writes via settings put, permission grants via pm grant are saved and persist across reboots, so it would be a one-time inconvenience for users.

To summarize this thread a bit:

  • Browsers get away with code execution through JIT compilation with a sandboxed language (JS)
  • Putting packages in separate apps would work, but sharedUID is already deprecated
  • Distribution on the Play Store may not be that important, but AOSP will likely start blocking low API levels in the future
  • UserLand works on high API levels by including proot in the apk
  • KVM would turn Termux into a VM software (with associated loss of native functions) and would require root
  • Using isolatedProcess sandbox would work, comply with Play Store policies (through sandboxing), and if I understand isolated services correctly would also fix phantom process killing, but would require a complex setup for executing system calls not allowed in the sandbox
  • WASM-based solutions would work, but require even more extensive patches to packages

Personally I think using something like proot is the least amount of work and would require the least amount of changes.
I also though about making an alternative implementation of proot to make it faster using seccomp (which every android version Termux supports should have AFAIK). If you like I can look into that more.

@tareksander Thanks for the summary, it seems accurate to me.

Regarding proot and WASM, please see: https://github.com/termux/termux-packages/wiki/Termux-and-Android-10/3e8102ecd05c4954d67971ff2b508f32900265f7#alternate-solutions

Theoretical suggestions, especially ones like "custom binary loaders" or something extremelly ridiculous like "rewrite everything in WASM" are NOT ACCEPTED!

Suggestions to use proot to execute everything are not accepted. Proot is not stable and still against Google Play policy. It also not known how such solution will be viable in long-term.

(I don't know why all of these details were removed from the latest revision of the wiki page despite this still being a pressing issue.)

Using proot as a binary loader is still a W^X violation; it's just one of the many W^X bypasses that still exist. It's clearly against Google's policy and I don't know how UserLAnd manages to stay on the Play Store despite this.

Daniel Micay speculates here that Android is moving towards blocking all W^X bypasses (i.e. methods of executing downloaded code) inside the regular app sandbox (untrusted_app). Firefox is currently the main blocker for this, since it doesn't use isolatedProcess for JIT (yet), like Chromium does. Support for executing downloaded code inside the isolated_app sandbox can never be removed because it would fundamentally break JIT in browsers.

Doing everything inside isolated_app while forwarding syscalls to untrusted_app could work, and I don't think there's anything Google could do at the technical (rather than policy) level to prevent this. If all syscalls are forwarded unconditionally, this is clearly not a meaningful sandbox and won't comply with Google Play policies, but that won't matter if Termux doesn't care about distributing through the Play Store.

Importantly, we are left with the following conclusions:

  • There is no way to comply with Google Play's policy unless a meaningful sandbox is implemented, and that probably can't be done for Termux.
  • Google seems to be moving towards blocking all direct W^X bypasses, but there will always be roundabout ways to execute downloaded code with the full privileges of untrusted_app. For now, there are easy bypasses like proot. In the future only solutions such as isolated_app execution + syscall forwarding may be possible, but it will still always be possible in some way.

Given this, I don't see why Google shouldn't just add a EXECUTE_UNVERIFIED_CODE development permission as I described in my earlier comment. It saves us the work of building an isolated_app sandbox, just to poke a bunch of holes in it, resulting in a "security theater" sandbox that doesn't have any advantage over just running the downloaded code directly in untrusted_app.

Has anyone here mentioned pKVM yet? It's basically a KVM hypervisor that Google is eventually gonna bake into Android as a Project Mainline module, and even if this kinda thing isn't exactly a top priority for what Google actually wants to do with it, projects like kdrag0n's Nestbox already show that pKVM may be viable in the long run for providing a similar experience to what's currently offered by UserLAnd and/or Termux.

@TheGentleChainsaw That's definitely an interesting possible solution.

QEMU and other VMs were discussed in the previous thread: https://github.com/termux/termux-packages/wiki/Termux-and-Android-10/b418b8342c4ad08ef1d3b63b8db46e4019bed40b#alternate-solutions

Problems with QEMU:

  • Performance hit (still applies to pKVM but much less so)
  • "Environment isolation make it unsuitable for using Termux as terminal emulator for Android" (quote from above wiki post)

Additional problem with pKVM is that Termux aims to have broad device support, and currently pKVM is only available without root on the Pixel 7. We don't know what Google's future plans for this will be.

Proot essentially uses QEMU behind the scenes.

There's also another interesting project that is derived from Unicorn, which is also derived from QEMU, called Qiling. You can put the SDK of the system you want to emulate (even bios), and it will load it.

Proot essentially uses QEMU behind the scenes.

No, it uses ptrace to intercept system calls made by the applications. It's not a VM.

https://github.com/termux/proot/blob/16f235f624931b3a9d96a2b6b2d687ed3d172852/doc/proot/manual.txt

In the docs it says it uses QEMU user, so that's why you don't need real
root to mount.

On Mon., Feb. 6, 2023, 16:51 tareksander, @.***> wrote:

Proot essentially uses QEMU behind the scenes.

No, it uses ptrace to intercept system calls made by the applications.
It's not a VM.


Reply to this email directly, view it on GitHub
#2155 (comment),
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AD7DVCBECZLAQOQLUMVYJLDWWGMABANCNFSM47X5HETA
.
You are receiving this because you were mentioned.Message ID:
@.***>

Only when you run something made for a different cpu architecture.

Importantly, we are left with the following conclusions:

* There is no way to comply with Google Play's policy unless a meaningful sandbox is implemented, and that probably can't be done for Termux.

* Google seems to be moving towards blocking all _direct_ W^X bypasses, but there will always be roundabout ways to execute downloaded code with the full privileges of `untrusted_app`. For now, there are easy bypasses like `proot`. In the future only solutions such as `isolated_app` execution + syscall forwarding may be possible, but it will still always be possible in some way.

Given this, I don't see why Google shouldn't just add a EXECUTE_UNVERIFIED_CODE development permission as I described in my earlier comment. It saves us the work of building an isolated_app sandbox, just to poke a bunch of holes in it, resulting in a "security theater" sandbox that doesn't have any advantage over just running the downloaded code directly in untrusted_app.

The downside to such a permission is that Termux wouldn't be installable and usable like a normal Android app, you need a computer with adb or another wireless adb client app installed.

The "security theater" is the only solution for the really-long term, and when you're at it with poking holes in the sandbox, you might as well make the holes controllable by the user, so you can run actually unsafe code. Something like multiple isolated prefixes are realizable, prefix path independency in general is a nice bonus.

Browsers also give JS limited file access and things like that, so I think even if we allow the code quite some things it would follow Play Store policies, because the access to Android APIs isn't unrestricted. Together with the prefix path independency there could be a new version on the Play Store, and the old version will be shadowbanned soon anyways.

I'm wondering if anyone has asked the Android team if they'd be willing to add a permission to bypass the W^X restriction on execve()

Perhaps Google could add a development permission that allows bypassing W^X, i.e. something like EXECUTE_UNVERIFIED_CODE.

I have thought about that too and do plan on asking google when I get time and resources, even if to no avail.

But its not android os framework that's blocking execution, but selinux policies for app processes assigned the untrusted_app* domains, which are managed by the kernel. So even if a permission was added, to allow specific apps to execute code would require android to add additional domains that don't have such restrictions, which would then be assigned to the app process depending on permission status when app zygote process is specialized by passing a custom seInfo for the package. Currently, there are 4 untrusted_app* domains for which restrictions apply, i.e untrusted_app_29, untrusted_app_30, untrusted_app_32 and untrusted_app. It "should" be possible to add 1 or 4 _dev_app domains that inherit from their respective _app domains, with an exemption for execution and any other policy exemptions that may be required in future.

Not sure how much extra work would be required to implement this, but I currently don't have the time to build AOSP and nor have the storage space or a test device to test my design. Maybe android os devs could suggest something different, but official support with something like this would be the best solution, specially so that termux and other apps can target latest android version. However, I am not sure if google would be willing to add this, seems not as likely. They even made the READ_LOGS permission in android 13 which can only be granted over adb pretty useless, by showing a prompt every time logcat command is run unless in a few second timespan. They didn't give any reason for it either and didn't even respond to my suggestion for adding an allow till next reboot option, so I don't really have any hopes. However, logs can contain privileged info and allowing execution for app processes with a development or appops permission granted over adb won't give any other special permissions to the app, so its not a big security risk. Moreover, adb shell user can execute files anyways, so if app uses adb to request access for execution, it could execute code with adb anyways, with much higher privileges.

https://cs.android.com/android/_/android/platform/system/sepolicy/+/cfdea5f4f3574385d739c1269e6c25783c109857

https://cs.android.com/android/platform/superproject/+/android-13.0.0_r31:frameworks/base/services/core/java/com/android/server/pm/SELinuxMMAC.java;l=373

https://cs.android.com/android/platform/superproject/+/android-13.0.0_r31:frameworks/base/core/java/com/android/internal/os/Zygote.java;l=417

https://cs.android.com/android/platform/superproject/+/android-13.0.0_r31:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp;l=1753

https://cs.android.com/android/platform/superproject/+/066bed72:external/selinux/libselinux/src/android/android_device.c;l=90

https://cs.android.com/android/platform/superproject/+/066bed72:external/selinux/libselinux/src/android/android_seapp.c;l=291

https://source.android.com/docs/security/features/selinux/implement#context-files

Asking google for additional selinux domains may not be too big a request. They have added it for their own gmscore app too which has different policies than other untrusted apps, but only if its installed as a priv-app (which it is on most devices) and has existed since 2019, so denying our requests would be partially hypocritical. with exemptions to the same exec restrictions that apply to other apps violating their own W^X policy, (Edit: It cannot exec() files and only dlopen() files from its app data directory which is also allowed for other untrusted app domains.)

https://cs.android.com/android/platform/superproject/+/android-13.0.0_r31:system/sepolicy/private/gmscore_app.te;l=73

https://cs.android.com/android/_/android/platform/system/sepolicy/+/c46a7bc759049445cf1b2d09eab4d5018f690aa8

The downside to such a permission is that Termux wouldn't be installable and usable like a normal Android app, you need a computer with adb or another wireless adb client app installed.

Termux could ship static adb binary inside the apk itself or use a java based client, no need for a separate app.

@tareksander Certainly it wouldn't be ideal to require adb to use Termux.

Personally I think a more reasonable version of the theoretical RUN_UNVERIFIED_CODE permission would be an auto-grant/"normal" level permission (similar to the other arguably more dangerous auto-grants like INTERNET and QUERY_ALL_PACKAGES), and Google could just block any apps that use it from the Play Store. This alone is a significant deterrent that ensures most apps won't use it. It also allows each app store to enforce its own policy regarding unverified code rather than forcing everyone to comply with Google Play's decisions. For example, alternative app stores like F-Droid could only approve apps using the permission if they demonstrate that it's absolutely necessary. F-Droid already lists all the auto-grant permissions for each app before the user installs them.

I pitched the more "hardened" concept for the permission because I know Google doesn't like to backtrack too much on security features once they're implemented. I'd consider it a win if they even considered implementing the "hardened" version. I'd consider it a bigger win if they considered implementing the permission as I described in this comment, but that's probably less likely.

@agnostic-apollo Good info!

I'm not sure opening an issue in the public Android issue tracker will be very effective. Perhaps the project could contact someone like topjohnwu. He works on the Android platform security team, and he's also the author of Magisk (a popular Android rooting tool), so he should be able to empathize with powerusers.

I did plan on asking @topjohnwu on what alternate would android provide if they removed support for sharedUserId for user apps that need to execute files since we obviously can't ship a single apk with 10s of GBs in size for our 1000s of packages. He worked on changes to sharedUserId for android 13 and also tweeted about it, so he may have more info on its future and could discuss our case with the internal team working on it. Didn't get time to do it...

Also, I am not in support of sharedUserId packaging as mentioned above, but at least it is a fallback option and if not viable for termux, it can be viable for other apps.

We are not removing shared UID as there are legitimate use cases like you mentioned

(Personal opinion follows)

Ideally, we ban any non priv-apps from using shared UID all together at some point, and in the meantime slowly and painfully migrate most priv-apps out of shared UID.

https://twitter.com/topjohnwu/status/1534654599314821120

One downside to the permission is that it would ship in Android 14 as the soonest option, so you'd need 2 versions of Termux: One with the target API level < Q for Android 6 - 13, and one with the current API level for Android 14+.

Moreover, adb shell user can execute files anyways, so if app uses adb to request access for execution, it could execute code with adb anyways, with much higher privileges.

I'd be a bit uncomfortable with executing everything with higher privileges, I access web content (so pretty untrusted) with curl and the like, which may have vulnerabilities.

So the current realistic proposals are (in order of (estimated by me) work):

  • Requesting a RUN_UNVERIFIED_CODE permission to be added to Android
    • Only applies for Android versions it will be added to and after
  • include proot
    • would also fix the dynamic prefix problem
    • performance degradation
  • Using an adb client in the app and run everything over that
    • runs at higher privilege than before
  • custom sandboxing with isolated_app
    • would also fix the phantom process problem, since Android knows about all the processes
      • OOM-killing can be prevented by binding the services with a high priority from the Termux foreground service
    • would also fix the dynamic prefix problem
    • performance degradation

@tareksander Good summary of possible solutions. Note that as I described before proot might be a very long-term option, but it'll still probably work for quite some time, so it's not unreasonable IMO.

I think what @agnostic-apollo was suggesting was that Termux ships a wireless adb client (that connects to the ADB port running on localhost) whose job it is to simply grant the RUN_UNVERIFIED_CODE permission to Termux, and that's it. From there ADB is no longer used and you can disable developer options if you want.

I think what @agnostic-apollo was suggesting was that Termux ships a wireless adb client (that connects to the ADB port running on localhost) whose job it is to simply grant the RUN_UNVERIFIED_CODE permission to Termux, and that's it. From there ADB is no longer used and you can disable developer options if you want.

That's included in the RUN_UNVERIFIED_CODE proposal, since it's not a problem to do that I didn't make a note for that.
The other proposal was to run everything through adb shell though.

Note that as I described before proot might be a very long-term option, but it'll still probably work for quite some time, so it's not unreasonable IMO.

Yeah, unless we immediately want a solution that works reliable even after 2030 or something like that, proot is viable.

Using an adb client in the app and run everything over that

Btw, someone already did something similar to this: https://play.google.com/store/apps/details?id=com.draco.ladb

It's not something I would personally use because it has an uncomfortable level of access to my phone over ADB (and the "wireless ADB" feature isn't meant to be enabled long-term, I think the system probably disables it after a certain amount of time or across reboots).

custom sandboxing with isolated_app [...] would also fix the dynamic prefix problem

This would also be a significant improvement to Termux. I've personally run into issues where I've wanted to run Termux in a secondary user profile but it's not possible as it stands.

It's not something I would personally use because it has an uncomfortable level of access to my phone over ADB

That's also my issue with it.

custom sandboxing with isolated_app [...] would also fix the dynamic prefix problem

This would also be a significant improvement to Termux. I've personally run into issues where I've wanted to run Termux in a secondary user profile but it's not possible as it stands.

I looked at the SELinux policies that are enforced additionally for isolated_app, and it mainly limits filesystem access and network sockets, but allows reading and writing to them if a file descriptor is passed to the process. That is quite doable with a broker. Exec would also have to be emulated, because no file can be accessed, and the Java part will have to stay active to communicate with the broker. Fork probably also needs to be emulated, to avoid phantom processes, and I don't know if a Binder connection can live through a fork. But given that read/writes are allowed without anything else (proot has to stop for all system calls IIRC), performance shouldn't be that bad, fork, exec, open/rm/etc. and socket creation are more of a rare occasion relative to everything else a program does. It should probably be better than proot.

One downside to the permission is that it would ship in Android 14

Yeah, we will just have to create another variant. However, android 14+ users won't be forced to use it until targetSdkVersion <= 28 support gets removed, which likely won't be for some time hopefully.

I'd be a bit uncomfortable with executing everything with higher privileges,

I meant if an app wanted to run some untrusted code, it could do it with adb. For termux to run everything with adb may be possible too, some users seem to have done it. But running code with shell user brings its own issues. For example, RUN_COMMAND permission isn't requested by com.android.shell package and termux-api wouldn't work either, unless ssh is used, etc. Other normal android permissions may be missing too.

would also fix the phantom process problem, since Android knows about all the processes

No, it should not. Processes are detected with cgroup.procs and any processes started with the separated isolated ProcessRecord would be listed in it.

https://www.reddit.com/r/termux/comments/yuwr4f/keeping_the_script_alive_even_after_termux_app_is/

https://cs.android.com/android/_/android/platform/frameworks/base/+/refs/tags/android-12.0.0_r32:services/core/java/com/android/server/am/ProcessRecord.java;l=81

isolated_app would likely be worse than the sharedUserId solution, its complete isolation, random uids assigned to it on creation that's different from termux app uid, restricted apis, lot of big issues.

I think the system probably disables it after a certain amount of time or across reboots).

adb wireless needs to be enabled on every reboot with a complex pairing process on newer android versions. If our custom permission would need to be granted on every boot, then same would be required, unless a prompt like logcat is shown instead of granting the permission.

I've personally run into issues where I've wanted to run Termux in a secondary user profile but it's not possible as it stands.

It will be supported for rooted users in next termux app version.

#2765 (comment)

No, it should not. Processes are detected with cgroup.procs and any processes started with the separated isolated ProcessRecord would be listed in it.

But the processes wouldn't be "phantom", they host services that are bound by the app, which makes Android keep them alive.

If your design is to not fork "phantom" child processes from a single isolated process and assign a new isolated process to each new child process, then you will have to define x isolated services in the AndroidManifest.xml, like chrome does 40 (not that they are all used normally by it), and so you will still be limited to max processes you can run and complex jobs like compilation, servers, scripts, GUI that fork lot of processes would hit the limit pretty easily and crash or have to wait till pool is free. And if you are running 30-40 app processes+services in the app, memory and low memory killers will likely have something to say about that too.

https://github.com/chromium/chromium/blob/6bb4aac8006c845f61d711d9adc08165daca24ae/chrome/android/java/AndroidManifest.xml#L1222

If your design is to not fork "phantom" child processes from a single isolated process and assign a new isolated process to each new child process, then you will have to define x isolated services in the AndroidManifest.xml, like chrome does 40 (not that they are all used normally by it), and so you will still be limited to max processes you can run and complex jobs like compilation, servers, scripts, GUI that fork lot of processes would hit the limit pretty easily and crash or have to wait till pool is free. And if you are running 30-40 app processes+services in the app, memory and low memory killers will likely have something to say about that too.

https://github.com/chromium/chromium/blob/6bb4aac8006c845f61d711d9adc08165daca24ae/chrome/android/java/AndroidManifest.xml#L1222

You only have to define one, you can create as many instances of it as you like.

OOM-killing can be avoided with binding priority. Since Termux has a foreground service, it'll be killed last before processes with showing Activities.

Right. However, its added in android 10, so would need a separate variant.

Bind does help, but can't avoid killing. And phantom process killing in android 12L+ is not too big an issue to use isolated processes for it, its solvable with a one time command.

Also I don't know what further restrictions currently exist in isolated app processes and what can easily be passed between normal and isolated app processes and what restrictions will be added in future. It would be more like a hack, at least sharedUserId way would have consistency with normal app process and would comply with policies. Some issues are documented at #1072 (comment)

@sucicf1 Very large set of packages. That's why not to use it.

There are limits:

  • Max size per asset pack is 512 MB.
  • The total download size of all asset packs per installation must not exceed 2 GB.
  • The total amount of all asset packs per application bundle must not exceed 50.

As of now Termux has 2000 packages. Considering amount of supported architectures, that's about 8000 packages in total.

P.S. We unlikely ever get back to Play Store. First of all we are locked out from the account where currently Termux is added.

Don't think there is a way to even symlink asset files.

@sucicf1 Another issue with that approach is that it makes Termux depend on Google Play Services, which means it won't work on devices without them, and it can't be uploaded to F-Droid anymore.

I do wonder how Google Play Services is able to provide this functionality to apps though, and if it's something we can re-create for ourselves. Hopefully it doesn't depend on the special SELinux domain that Google gives itself as per #2155 (comment)?

Looks like it's based on split APKs? Unprivileged applications can install those: https://github.com/Aefyr/SAI

Combined with the Android 12 unattended updates API, I think theoretically Termux could automatically add components to itself without prompting the user each time?

There'd still be the problem that the user should be able to compile their own code and run it. Perhaps there could just be a public signing key for Termux (same as you do now for the GitHub releases) so the app could create split APKs on-demand, sign and install them?

It would still be a lot more convenient if they just let us run our code directly :/

Additional problem with pKVM is that Termux aims to have broad device support, and currently pKVM is only available without root on the Pixel 7. We don't know what Google's future plans for this will be.

Looked into Android Virtualization Framework (which pKVM is part of) a bit more, and the current plan is pretty clearly to make it a standard feature, or at least a more commonly-usable one, by the time Android 14 releases to manufacturing. What's more is that, since it'll be a Project Mainline module, users might not even need 14 or newer to be able to use it.

It seems like the key blocking issue at the moment is getting AVF to support virtualisation backends that will play nice with the major SoC product families -- something that's already being worked on by Qualcomm and MediaTek, and presumably other vendors as well.

Obviously, still not viable as a short-term solution. But I feel like it makes more sense to think long-term since, again, we've got quite a while still before API 28 gets excluded from new Android builds.

My suspicion is that, strategically, pKVM is a route for Google to introduce Fuchsia into their hardware ecosystem without necessitating a whole slew of agreements and deals with manufacturers to migrate away from Android. If that is the case, then virtualization would likely be available to end-users and developers, rather than just manufacturers, as Google would want to encourage an ecosystem of Fuchsia applications.

@TheGentleChainsaw The other problem with it is still a big one: "Environment isolation make it unsuitable for using Termux as terminal emulator for Android" (quote from the Termux developers). This issue might make it a non-starter depending on the project's goals going into the future. Personally I would really miss the direct interaction with Android you get from the current version of Termux. I think it's super cool that my code is running "on bare metal", and that's something you don't get on iOS.

You mentioned kdrag0n's Nestbox earlier. Maybe the folks that don't need the Android integration Termux offers can just use that instead of Termux? Looks like it even uses a modified Termux as the terminal.