Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisit the Android W^X problem #2155

Open
iamahuman opened this issue Jul 3, 2021 · 138 comments
Open

Revisit the Android W^X problem #2155

iamahuman opened this issue Jul 3, 2021 · 138 comments

Comments

@iamahuman
Copy link
Contributor

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

@iamahuman
Copy link
Contributor Author

iamahuman commented Jul 3, 2021

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.

@Grimler91
Copy link
Member

Grimler91 commented Jul 3, 2021

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.

@RalfWerner
Copy link

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.

@suhan-paradkar
Copy link

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....

@ghost
Copy link

ghost commented Jul 18, 2021

@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.

@ghost
Copy link

ghost commented Jul 18, 2021

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.

@RalfWerner
Copy link

RalfWerner commented Jul 18, 2021

  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."

@ghost
Copy link

ghost commented Jul 18, 2021

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.

@RalfWerner
Copy link

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?

@ghost
Copy link

ghost commented Jul 18, 2021

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.

@StarkZhidian

This comment has been minimized.

@agnostic-apollo

This comment has been minimized.

@xloem
Copy link

xloem commented Sep 13, 2021

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.

@Vixeliz
Copy link

Vixeliz commented Oct 11, 2021

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.

@ghost
Copy link

ghost commented Oct 11, 2021

@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.

@Vixeliz
Copy link

Vixeliz commented Oct 11, 2021

@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.

@ghost
Copy link

ghost commented Oct 11, 2021

@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

@Vixeliz
Copy link

Vixeliz commented Oct 12, 2021

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

@RalfWerner
Copy link

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.

@iamahuman
Copy link
Contributor Author

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

@ghost
Copy link

ghost commented Oct 13, 2021

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.

@Manu99it
Copy link

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

@PsiCodes
Copy link

@caleb-allen Yes, I am able to install Python libraries, but installing libraries can be done with just the Python executable packaged with the application.

@caleb-allen
Copy link

@PsiCodes don't some python libraries include C dependencies? Like OpenCV or Pytorch. Python itself is interpreted but its dependencies are not - if not using proot, there must be a custom loader of some kind

@PsiCodes
Copy link

PsiCodes commented Jun 20, 2023

@caleb-allen Sorry, I thought you were talking about Pip. Yes, Pydroid 3 allows you to download these libraries, but they cannot be installed directly via pip in terminal. Pydroid 3 has its own repo for downloading such libraries that requires some external lib.

@beroal
Copy link

beroal commented Jun 30, 2023

Allowing a desktop to execute commands on an Android device is a security risk because the desktop may be infected. (I'm talking about adb.)

@sylirre
Copy link
Member

sylirre commented Jun 30, 2023

Allowing the user to run programs on desktop is much higher security risk, isn't it? ADB commands are one-sided, the desktop can send commands to Android device but not vice versa. So how accessing Android device through ADB can lead to security risks of the desktop computer?

I've heard about the cases where infected desktop was able to infect Android device through ADB, but never the opposite direction.

If desktop executes a command that possess certain security risk, then there are two variants: either user doing that intentionally or the desktop computer was already infected.

Btw, @beroal how your comment is relevant to the topic of #2155?

@agnostic-apollo
Copy link
Member

I've heard about the cases where infected desktop was able to infect Android device through ADB, but never the opposite direction.

This is what they probably meant. An infected desktop could be a security risk to android over adb so why does android allow that. To answer, adb requires turning on developer options and debugging and pairing or physical usb access to an unlocked device, so not easy to exploit. Apps can also use adb to run commands, like say done by tasker.

@beroal
Copy link

beroal commented Jul 1, 2023

I've heard about the cases where infected desktop was able to infect Android device through ADB, but never the opposite direction.

This is exactly what I mean. The security of an Android device.

Btw, @beroal how your comment is relevant to the topic of #2155?

I like the RUN_UNVERIFIED_CODE solution. If it will ever be implemented, using adb in order to install Termux will be a security risk in addition to being an inconvenience. Just thinking ahead.

@EternityForest
Copy link

I've opened #3496 to make my case for why I think bundling binaries into the APK is a good idea. It's pretty much the same pattern as Linux containers which is the foundation for just about all IT these days.

Linux's crazy web of dependencies is fairly hard to deal with any other way in production or consumer applications, and the ability to make fixed bundles would allow using tmux in end-user applications.

RUN_UNVERIFIED_CODE is fantastic, and really a necessity to keep Android from becoming just another iOS style load of garbage, but there's no reason both solutions can't exist in parallel.

@agnostic-apollo
Copy link
Member

Well, so I have been an idiot thinking that for the APK packages design (TAPM), the packages APKs will require the same sharedUserId as the termux app. When in fact, any app can execute native libraries (or run APKs) of other apps in /data/app/*/lib/ directory, since they have the rwxr-xr-x permission, basically others can read and execute them, but not write to them. The APKs and native libraries are owned by the system user and not by the app user. The /data/app files are assigned the apk_data_file selinux file context and android through selinux policies (app.te), also allows any untrusted_app to execute them (but not system_app from rw /data partition). Basically, it is irrelevant whether android removes sharedUserId in future for untrusted apps or not, this design can work if needed. The /data/data files are assigned the different app_data_file selinux file context. Not only that, since not all apps use or can shift to sharedUserId if they didn't start with it, they can still use this design to have additional APKs for packages anytime they want, like think native support in Tasker for any package without root. The sharedUserId requirement has been a misconception for me and others (1, 2, 3).

# Allow apps to read/execute installed binaries
allow appdomain apk_data_file:dir r_dir_perms;
allow appdomain apk_data_file:file rx_file_perms;

# Sensitive app domains are not allowed to execute from /data
# to prevent persistence attacks and ensure all code is executed
# from read-only locations.
neverallow {
  bluetooth
  isolated_app
  nfc
  radio
  shared_relro
  sdk_sandbox
  system_app
} {
  data_file_type
  -apex_art_data_file
  -dalvikcache_data_file
  -system_data_file # shared libs in apks
  -apk_data_file
}:file no_x_file_perms;

On top of that, since there is no sharedUserId requirement, there is also no requirement for having the packages APKs to have the same signature as the termux app. However, signatures are obviously important for security, so termux can have a new single private key for signing packages APKs that is checked for when a user requests a new package installation into $PREFIX. This key will be different, but shared for GitHub (debug+our new key), F-Droid, Samsung (our new key), and PlayStore builds, since we don't have access to F-Droid keys and we can't sign our packages APKs with it, unless we deploy packages there. It would be easier for termux-packages development build as well to have single key that all app builds can use. Users who want to compile their own code and package into an APK can use their own custom key and then whitelist it in termux properties to allow installation.


PlayStore does not seem to have any restriction regarding loading native libraries of other apps, they only need to be inside APKs in PlaySore. All app builds outside PlayStore can use our own hosted repos and mirrors directly.

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 (such as dex, JAR, .so files) from a source other than Google Play. This restriction does not apply to code that runs in a virtual machine or an interpreter where either provides indirect access to Android APIs (such as JavaScript in a webview or browser).

Although, not sure how one is supposed to protect against this for a general terminal app.

Apps or third-party code, like SDKs, with interpreted languages (JavaScript, Python, Lua, etc.) loaded at run time (for example, not packaged with the app) must not allow potential violations of Google Play policies.

A drawback for APK design is that it will need 2x space for each package. Binaries (/bin) and libraries (/lib) both need to be in the app native library directory to be allowed execution by android (avc entries are generated for both for unstrusted_app_27), so they will need to be extracted from APK to app native library directory, requiring 2 copies.

Other normal files (/etc, /share, etc) that normally should be writable (like for conffiles) must not be symlinks and would not require extraction to app native library directory and would need to be copied from APK to $PREFIX, however since extractNativeLibs/useLegacyPackaging would work for all native libraries or none, that would result in 3x space usage if they are copied. However, they can be bundled as an APK asset instead of a native library, so that even they require 2x space, but that would obviously complicate things, so can be seen if worthwhile.


I have tested this design on Android 14 (Google APIs userdebug build) and Google 11 (Google Play release build) and is working fine for the com.termux bootstrap generated with generate-bootstraps.sh --android10 and then added as native libraries to the app with the package name com.termux.tapm.rootfs_0.termux_bootstrap and then Termux com.termux package installing the bootstrap in its own $PREFIX. Both apps used targetSdkVersion=34 (Android 14), had different signatures, and com.termux.tapm.rootfs_0.termux_bootstrap did not use sharedUserId and were tested for debug and release APK builds and no avc entries were generated.

$ getprop ro.build.fingerprint
google/sdk_gphone64_x86_64/emu64x:UpsideDownCake/UPP2.230217.004/9663077:userdebug/dev-keys

$ env | sort | grep TERMUX_
ENV__ROOT_SCOPE=TERMUX_
TERMUX_APP__APK_FILE=/data/app/~~Tn249ZOX-wa4kZT9uuKW-g==/com.termux-8Fo-uB5C2dL9xB9NIhQPlA==/base.apk
TERMUX_APP__APK_RELEASE=GITHUB
TERMUX_APP__BUILD_VARIANT=bootstrapVariant=apt.android-7;targetSdkVersion=34
TERMUX_APP__DATA_DIR=/data/user/0/com.termux
TERMUX_APP__IS_DEBUGGABLE_BUILD=true
TERMUX_APP__IS_INSTALLED_ON_EXTERNAL_STORAGE=false
TERMUX_APP__PACKAGE_NAME=com.termux
TERMUX_APP__PID=5071
TERMUX_APP__SE_FILE_CONTEXT=u:object_r:app_data_file:s0:c169,c256,c512,c768
TERMUX_APP__SE_INFO=default:targetSdkVersion=34:complete
TERMUX_APP__SE_PROCESS_CONTEXT=u:r:untrusted_app:s0:c169,c256,c512,c768
TERMUX_APP__TARGET_SDK=34
TERMUX_APP__UID=10169
TERMUX_APP__USER_ID=0
TERMUX_APP__VERSION_CODE=118
TERMUX_APP__VERSION_NAME=0.119.0-beta1
TERMUX_VERSION=0.119.0-beta1
TERMUX__AM_SOCKET_SERVER_ENABLED=true
TERMUX__AM_SOCKET_SERVER_PATH=/data/data/com.termux/files/apps/com.termux/termux-am/am.sock
TERMUX__APPS_DIR=/data/user/0/com.termux/termux/apps
TERMUX__CORE_DIR=/data/user/0/com.termux/termux/core
TERMUX__DATA_HOME=/data/data/com.termux/files/home/.termux
TERMUX__HOME=/data/data/com.termux/files/home
TERMUX__PACKAGE_MANAGER=apt
TERMUX__PACKAGE_VARIANT=apt.android-7
TERMUX__PREFIX=/data/data/com.termux/files/usr
TERMUX__ROOTFS=/data/data/com.termux/files
TERMUX__ROOT_DIR=/data/user/0/com.termux/termux
TERMUX__SHARED_USER_ID_APP_PACKAGES=com.termux


$ /system/bin/ls -lZh $PREFIX/bin/bash
lrwxrwxrwx 1 u0_a169 u0_a169 u:object_r:app_data_file:s0:c169,c256,c512,c768  124 /data/data/com.termux/files/usr/bin/bash -> /data/app/~~TjBAnoUJxGcSDGSDrK7-rQ==/com.termux.tapm.rootfs_0.termux_bootstrap-PbU_h-Q1BH4FonRHuVcNuA==/lib/x86_64/lib120.so

$ /system/bin/ls -lZh /proc/$$/exe
lrwxrwxrwx 1 u0_a169 u0_a169 u:r:untrusted_app:s0:c169,c256,c512,c768  0 /proc/7374/exe -> /data/app/~~TjBAnoUJxGcSDGSDrK7-rQ==/com.termux.tapm.rootfs_0.termux_bootstrap-PbU_h-Q1BH4FonRHuVcNuA==/lib/x86_64/lib120.so

$ /system/bin/ls -lZh /data/app/~~TjBAnoUJxGcSDGSDrK7-rQ==/com.termux.tapm.rootfs_0.termux_bootstrap-PbU_h-Q1BH4FonRHuVcNuA==/lib/x86_64/lib120.so
-rwxr-xr-x 1 system system u:object_r:apk_data_file:s0  806K /data/app/~~TjBAnoUJxGcSDGSDrK7-rQ==/com.termux.tapm.rootfs_0.termux_bootstrap-PbU_h-Q1BH4FonRHuVcNuA==/lib/x86_64/lib120.so


$ /system/bin/ls -lZhd /data/data/com.termux
drwx------ 7 u0_a169 u0_a169 u:object_r:app_data_file:s0:c169,c256,c512,c768  4.0K /data/data/com.termux

$ su -mm -c '/system/bin/ls -lZhd /data/data/com.termux.tapm.rootfs_0.termux_bootstrap'
drwx------ 5 u0_a171 u0_a171 u:object_r:app_data_file:s0:c171,c256,c512,c768  4.0K /data/data/com.termux.tapm.rootfs_0.termux_bootstrap


$ su -c 'dumpsys package com.termux 2>&1 | grep SharedUser'
    sharedUser=SharedUserSetting{36d4d91 com.termux/10169}
  SharedUser [com.termux] (36d4d91):

$ su -c 'pm list packages | grep termux'
package:com.termux
package:com.termux.tapm.rootfs_0.termux_bootstrap


$ apksigner verify --verbose --print-certs termux-app_apt.android-7.release_universal.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Number of signers: 1
Signer #1 certificate DN: CN=APK Signer, OU=Earth, O=Earth
Signer #1 certificate SHA-256 digest: b6da01480eefd5fbf2cd3771b8d1021ec791304bdd6c4bf41d3faabad48ee5e1

$ apksigner verify --verbose --print-certs termux-bootstrap-release.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Number of signers: 1
Signer #1 certificate DN: CN=Agnostic Apollo, L=Earth
Signer #1 certificate SHA-256 digest: d3be90deb8e1d9e4b8f2f397520f7e430788477e96d2f879eefdcf35518926a1


$ termux-am startservice com.termux/.app.TermuxService
Starting service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.termux/.app.TermuxService }

$ am startservice com.termux/.app.TermuxService
Starting service: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.termux/.app.TermuxService }

It was suggested in #1072 and internally to use on-demand features modules, but that ain't gonna work for PlayStore.

When on-demand feature modules are requested to be installed with Play Core APIs (not bundletool), they are initially installed under /data/data/<package_name>/files/splitcompat and made available to the app, but then at a later time installed by the system to the app apk directory under /data/app, when app can be killed/restarted.

You are not actually installing them, you are effectively requesting the installation via the Play Core API, which emulates the installation until it can install it properly at a later time (usually overnight). This happens because an installation would otherwise require the restart of the application.

# find /data -wholename '*/splitcompat/*' -o -wholename '*/split*.apk' | sort | grep -E 'inputmethod'
/data/app/~~4dCOKOBWOLhdujjK0JJE1g==/com.google.android.inputmethod.latin-_PfgmU26mDH2zhyxJgHAMw==/split_brella_feature_split.apk
/data/app/~~4dCOKOBWOLhdujjK0JJE1g==/com.google.android.inputmethod.latin-_PfgmU26mDH2zhyxJgHAMw==/split_config.xxhdpi.apk
/data/app/~~4dCOKOBWOLhdujjK0JJE1g==/com.google.android.inputmethod.latin-_PfgmU26mDH2zhyxJgHAMw==/split_tenoranimation_feature_split.apk
/data/data/com.google.android.inputmethod.latin/files/splitcompat/112573422
/data/data/com.google.android.inputmethod.latin/files/splitcompat/112573422/verified-splits

But since /data/data files are assigned the app_data_file selinux file context, they will not be allowed to be executed (after extraction), until they are installed under /data/app and assigned the apk_data_file. I don't see anyway to directly install to system with Play Core APIs, but even if that were possible (like bundletool does), for every package installed, the Play Core API app would likely kill the base app, which is obviously terrible UX.

There is a PackageInstaller.SessionParams.setDontKillApp() method that enables the INSTALL_DONT_KILL_APP flag that has been added in Android >= 14 as a public API for when creating a package install session to not kill the app when split APKs are installed with the MODE_INHERIT_EXISTING flag, but can also be called with reflection+hidden-api-bypass since Android 7 when it was added. The --dont-kill flag is also supported by the pm install -p command. Since there would be no class or resource sharing between base and package APKs, it should work fine for our case I think. But since Play Core API is pre-installing to /data/data first and I am not sure whether it uses the flag, so termux PlayStore builds cannot use this way.

Moreover, using feature modules is not a good general solution for Android 10 restrictions since feature modules are only provided by Google PlayStore and so will be unusable on devices that don't have PlayStore or can't access Google (like China). Huawei has its own Dynamic Ability API, but even that would not be available for everyone. There is GloballyDynamic, that tries to solve multiple implementation problem and has its own implementation to host and install split APKs for devices that do not have play or huawei APIs and also uses setDontKillApp() and MODE_INHERIT_EXISTING. All of this is additional complications, not to mention that users will not be able to create custom code APKs without having the signing keys of the base app itself, since all splits will need to signed with same key, which won't be possible for F-Droid, PlayStore and our own new key and only for the public GitHub debug key.

Some additional interesting links

@fornwall
Copy link
Member

fornwall commented Oct 2, 2023

I posted a proposal how to work around the "no exec() in data folder" problem using termux-exec here: termux/termux-exec#24 - see the linked README there.

@termux termux deleted a comment from ETERNALBLUEbullrun Oct 2, 2023
@termux termux deleted a comment from ETERNALBLUEbullrun Oct 2, 2023
agnostic-apollo pushed a commit that referenced this issue Oct 7, 2023
#1072 needs extra attention

Fornwall is active again and work is already being done on #1072 for an alternate variant at termux/termux-exec#24 and the other alternate #2155 (comment) will be worked on in future.
@sls1005
Copy link

sls1005 commented Dec 2, 2023

The last time I checked, PyDroid offered a embedded terminal emulator on which pip install can be used. I remember using it to install numpy, which took a lot of time to compile. I'm not sure if that's still offered now as I'm no longer using it.

Also I suggest that if any of the breaking changes is to be made to target Android 10 or later, it should be released under another app name, package name, and account. Therefore if it's succeeds, we'll have one more choice on Android 10+; if it fails, only the newer version will be removed from Google Play, and the current users are unaffected. The current app can be maintained until the day Android drops the backward-compatibility.

@sylirre
Copy link
Member

sylirre commented Dec 2, 2023

@sls1005 You seem don't understand the issue with Play Store.

The problem is that application on Google Play is outdated and that happened for a reason: no Termux update can be submitted until necessary requirements would be met.

So in order to update the application on Play Store the app should integrate a fix for Android 10, no matter whether it is breaking or not.

Otherwise the outdated app on Play Store has to be unpublished, though the current maintainer team can't do so because lacking access to Google Play console.

Changing app package name is not easy task as would have a lot of consequences even if the old app would be kept.

@npjohnson
Copy link

npjohnson commented Dec 6, 2023

Per Nifty's request, was asked to drop in.

I can (and have) presented some RFC patchsets on behalf of the LineageOS org that have been merged into AOSP main.

With that said, seeing the general direction of this thread, if someone wanted to build out the permission "Allow application dynamic code execution" or whatever you choose to call it (I'd wire it us as a dev-settings toggle personally), you should topic the bare minimum changes to get it functioning, tag it [RFC], toss on AOSP Gerrit targeting main then ping me, I can route it to the right people for comments.

@DownrightNifty
Copy link

DownrightNifty commented Dec 7, 2023

Unfortunately, all developer options reset when you toggle the "developer options" switch in Settings. And while developer options are enabled, your build number annoyingly appears in the notification shade with no option to hide it. I prefer to keep developer options disabled most of the time.

I think it would be awkward if there were certain apps on your phone that only work while developer options are enabled and stop working as soon as they're turned off.

For these reasons, I would much prefer that it be a permission. More specifically, a development permission. These work differently than standard runtime permissions and must be granted over adb, as I described in my earlier comment/proposal. But importantly, development permission grants are persistent.

@npjohnson
Copy link

that is also an option. permission only grantable over adb.

@agnostic-apollo
Copy link
Member

Hi @npjohnson,

Thanks for dropping in. Great to hear about the patches and connects, would be useful when the time comes. I plan on working on it after the next major app release, whenever that happens, don't have time currently.

Apart from settings being reverted when developer options are disabled, it's unlikely that android team would accept a global toggle and technically they shouldn't, since all apps shouldn't be allowed to execute untrusted code and an app specific dev permission granted over adb would be the way to go and would have higher chances of actually being accepted. Will post some docs about all of this shortly.

@caleb-allen
Copy link

Here's an update to the Virtualization approach: there was a blog post just published by the Android Developers Blog called Virtual Machine as a Core Android Primitive, which shows some public movement on the Android Virtualization Framework.

Android 14 will allow privileged applications to start and manage VMs; previously, only the platform itself could do so. The blog calls out a few specific use-cases for privileged applications, including Biometric computations as well as DRM, both of which they say will be easier to update and manage across Android devices (no longer requiring code specific to each vendor's "secure compute" systems).

My understanding is that privileged applications can only spin up a VM image that is signed by Google or the device vendor. "Microdroid" is one such image, a stripped down version of Android and can be created on all Pixel devices from the Pixel 6 onwards. Microdroid retains the SELinux W^X policy which is sensible from the security standpoint.

In my opinion, it's unlikely Google will allow unrestricted virtualization by third party applications any time soon. However, specific vendors might, in ways that give a competitive edge (think Samsung DeX). Not sure this will bear fruit for something like Termux but it is perhaps something to keep an eye on.

@termux termux deleted a comment from Sahilkhan78609 Dec 13, 2023
@DownrightNifty
Copy link

DownrightNifty commented Dec 13, 2023

@agnostic-apollo I'd really hate to see Android become so locked down that you can't even have a terminal emulator. Is there any way I can donate to you to support the development of the AOSP permission to execute dynamically loaded code?

There are a surprising number of people who rely on Termux as part of their daily workflow, yet don't know that its prolonged existence is currently up in the air.

Recently there was even an article on LWN about it: https://lwn.net/Articles/936953/

Any mention of Termux frequently gets highly upvoted on Hacker News.

I'm down to create a blog post or GitHub gist attempting to rally up support for this change. I think it would receive much positive attention online.

@agnostic-apollo
Copy link
Member

agnostic-apollo commented Jan 1, 2024

Docs have been added for android app data file execute restrictions at following links.


@DownrightNifty Hey, thanks for the offer. Check https://termux.dev/donate for how to donate to me or preferably other termux devs currently. I already have funding for next couple of months, and it's not as much a money issue, as it's a time issue.

I have a gazillion things to do related to Termux and currently termux app updates and related work takes higher priority since they have been already been delayed for far too long (as LWN points out too) and more people are in greater need of the update with fixes and additions than any future breakage. I have been working on the updates full time for more than a year at this point, there is just so much work to do and everything is broken. Getting the permission added to AOSP is a priority for me too, just not the top priority and I do plan on looking into it after the releases like I have already said.

Go ahead if you want to make a blog post, that would be great. However, I think after all this time, all the important people who may be able to actually get a real fix implemented already know about it, but then again funding could help motivate someone to take charge.

Also a working hack is being worked on at termux/termux-exec#24 as mentioned above.

KitsunedFox pushed a commit to KitsunedFox/termux-monet that referenced this issue Jan 1, 2024
termux#1072 needs extra attention

Fornwall is active again and work is already being done on termux#1072 for an alternate variant at termux/termux-exec#24 and the other alternate termux#2155 (comment) will be worked on in future.
@sylirre

This comment was marked as off-topic.

@termux termux deleted a comment from Joppelchen Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests