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

[Feature]: Multi-user support #2765

Open
FossPrime opened this issue May 9, 2022 · 35 comments
Open

[Feature]: Multi-user support #2765

FossPrime opened this issue May 9, 2022 · 35 comments

Comments

@FossPrime
Copy link

FossPrime commented May 9, 2022

Feature description

Multiuser is still essential for maintaining privacy, as Android 12 has no way to stop apps from seeing what other apps you have installed. I can run Termux on my primary user as the app I'm hiding from has DRM protection that disables features, and Multi-user trips the DRM.

It would also be useful to have separate termux environments.

Screenshot_20220509-232949

Additional information

Nix-on-droid also doesn't work. I'll use termius instead.

@agnostic-apollo
Copy link
Member

Duplicate of #2291

as Android 12 has no way to stop apps from seeing what other apps you have installed.

Since android 11, if an app uses targetSdkVersion 30 (Android 11), it cannot see any other apps that have been installed, other than a few. The app runs in an isolated environment in which /data/data/<package_name> directories of other apps do not exist in its mount namespace, so it can't fingerprint other apps. The QUERY_ALL_PACKAGES permission can bypass the visibility though. So best use apps that target latest sdk or don't have QUERY_ALL_PACKAGES if you want hiding.

https://cs.android.com/android/platform/superproject/+/android-11.0.0_r48:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp;l=1280

https://developer.android.com/about/versions/11/privacy/storage#other-private-dirs

https://developer.android.com/training/basics/intents/package-visibility#package-name

Why are you trying to hide termux?

@ChiefMikeK
Copy link

has DRM protection that disables features...

@rayfoss What feature(s) are you needing that are missing?
There maybe exists a work-around for your use case.

@FossPrime
Copy link
Author

FossPrime commented May 11, 2022

... I'm not trying to hide Termux at all... I just don't use the owner account for anything but... work. 99% of the time i'm in a slave account, even Google Pay works in it.

I used the following app to findout that other work apps CAN see what other apps I have installed, zero permissions needed: https://play.google.com/store/apps/details?id=com.ytheekshana.deviceinfo&hl=en_US&gl=US
Even without an API, they could always open a port and conspire to correlate, deanonymize and connect my accounts. The effect is fairly immediate... try installing an app exclusive to India/Japan App and watch Tiktok start showing you Indian content/ad's.

Unfortunately I can't even switch to the owner account and install Termux there, as that might tip my employer know I don't live in the country I'm pretending to be in. I only have apps that are common in the area on that account.

@agnostic-apollo
Copy link
Member

I have installed, zero permissions needed: https://play.google.com/store/apps/details?id=com.ytheekshana.deviceinfo&hl=en_US&gl=US

The app has requested QUERY_ALL_PACKAGES and its automatically granted.

Lolz, you seem to have a lot of problems ;)

But termux prefix limitation has existed since the start. If you use limited packages, you can compile those packages for your secondary user prefix and termux should work, will of course require removing check in app, I may do that them myself in near future for a refactor required. Or maybe look into hacks mentioned in #2734, since you have the more motivation needed for secondary user support ;)

@Anonymous2716
Copy link

Does a work profile works for you?

@lars18th
Copy link

Hi,

Could be a solution a new script for the compilation environment supporting this?

  1. Compile Termux with a different "name" and "$PREFIX".
  2. Recompile a list of user selected packages for this "new" Termux.
  3. Recompile some Termux-plugins (example Termux-GUI) for this new target.
  4. Add some user files and installation scripts.
  5. Package all inside one <name.>APK

In this case the new App will be independent of the regular Termux, right?
Then this will solve termux/termux-packages#11253 too. 😉

@agnostic-apollo
Copy link
Member

https://github.com/termux/termux-app#Forking

Make sure to change sharedUserId. Also I don't know about Termux:GUI forkability.

@lars18th
Copy link

Hi @agnostic-apollo ,

https://github.com/termux/termux-app#Forking
Make sure to change sharedUserId. Also I don't know about Termux:GUI forkability.

It seems then that the forking option (create a fork package with a new package name) is a viable solution. Using this technique anyone can create a totally isolated environment. However, I feel this requires to be more user-friendly. Do you think it's a good idea to develop one script to complete all the tasks? So instead of manually execute all steps, execute one command only. One side advantage of this is the option to execute this inside a testing tool to check if all the environment+plugins+packages are compatible with the TermuxConstants. And then this functionality will be mainstream in the Termux project.

My objective is to "package" custom user Apps (linux binaries+Termux-GUI scripts) inside an APK to use them as standalone Android Apps. I hope you want to support this.
Regards.

@Grimler91
Copy link
Member

It seems then that the forking option (create a fork package with a new package name) is a viable solution. Using this technique anyone can create a totally isolated environment. However, I feel this requires to be more user-friendly. Do you think it's a good idea to develop one script to complete all the tasks?

PRs are welcome. For testing purposes such a script might be useful, but I suspect that a real fork would anyways want to customise things like which packages to include in bootstrap, or which addon apps to include, so not sure how helpful it would be for forkers

@agnostic-apollo
Copy link
Member

Real forks would also make other changes to TermuxConstants, like app name, url changes, etc and would use Android Studio to make changes and not scripts. Changes would also be required in build.gradle and strings.xml and other files. And like grimler said, desired packages would also be custom to forker. The desired package manager would also require config. So this would be lot of work to automate. You are free to create a script and see how it goes.

@tareksander
Copy link
Member

Hi @agnostic-apollo ,

https://github.com/termux/termux-app#Forking
Make sure to change sharedUserId. Also I don't know about Termux:GUI forkability.

It seems then that the forking option (create a fork package with a new package name) is a viable solution. Using this technique anyone can create a totally isolated environment. However, I feel this requires to be more user-friendly. Do you think it's a good idea to develop one script to complete all the tasks? So instead of manually execute all steps, execute one command only. One side advantage of this is the option to execute this inside a testing tool to check if all the environment+plugins+packages are compatible with the TermuxConstants. And then this functionality will be mainstream in the Termux project.

My objective is to "package" custom user Apps (linux binaries+Termux-GUI scripts) inside an APK to use them as standalone Android Apps. I hope you want to support this. Regards.

For forking Termux:GUI you just need to change the package name, and replace the package name accordingly in the am calls in the libraries, requiring you to fork them, too. Termux:GUI supports the same Android version range as Termux, but Android 5 will probably not work.

@Pxys-io
Copy link

Pxys-io commented Nov 18, 2022

?Any updates about the issue? I have not been able to use termux because of that! Thankz

@FossPrime
Copy link
Author

?Any updates about the issue? I have not been able to use termux because of that! Thankz

@kdrag0n 's NestBox requires Developer Mode and wireless debugging... I couldn't set it up, so it also has similar problems.

@agnostic-apollo
Copy link
Member

For people with rooted devices, it should be possible to mount secondary user private app data directory assigned to termux at /data/data/com.termux at app init as discussed in #2168 (comment)

I have added support locally to run commands at app init, not sure if I will have time to add in-built support to do mounting before this release, already got too many things. Can at least ignore the secondary user check if prefix is accessible.

No plans for other ways.

Have seen NestBox updates on twitter by @kdrag0n, looks pretty interesting, if termux ever goes away, there is at least some hope if non-root support is maintained by google in future.

@n1lby73
Copy link

n1lby73 commented Dec 27, 2022

Is there any solution to this yet cause I'm also I'm need of it

@agnostic-apollo
Copy link
Member

Next version should have multi user support for termux on secondary user and if users want to install termux on adoptable storage, assuming root access has been granted to termux. Tested on A11 and A13. I still need to finalize this like add docs and add settings toggle, etc.

Secondary User

termux-secondary-user

Adoptable Storage

termux-adoptable-storage

@RealEthanPlayzDev
Copy link

Next version should have multi user support for termux on secondary user and if users want to install termux on adoptable storage,

@agnostic-apollo
Hi, are there any actions builds that allow multi-user? I've tried getting the latest one but it still errors about hardcoded bootstrap prefix

Or is there another way to get multi-user (like recompiling the app manually from source)? I've read there is but theres no good guide on how to modify the source and bootstrap generation scripts to properly support it, I'd appreciate some help

@tareksander
Copy link
Member

AFAIK agnostic-apollo works in a local fork, so there is no way to try it until it's released.

@agnostic-apollo
Copy link
Member

Haven't pushed changes yet. And it will require root as I said. Compiling app with different prefix won't do much, you would need to recompile all termux packages as well.

@RealEthanPlayzDev
Copy link

RealEthanPlayzDev commented Jul 6, 2023

did you try proot? https://www.reddit.com/r/termux/comments/10h2bmn/how_to_run_termux_environment_through_proot_from/

@romanovj
I don't plan on using Termux from adb, I need the app to run literally on a different uid

Haven't pushed changes yet. And it will require root as I said. Compiling app with different prefix won't do much, you would need to recompile all termux packages as well.

@agnostic-apollo
Ah, I didn't catch the root requirement part (I can't root the device in question unfortunately). I think I'll be fine with recompiling the packages and bootstrap

I probably can work mostly from proot-distro (and in fact, 90% of the time I'm inside a archlinux proot, the only times I needed to exit proot was just updating termux packages), so technically all I need is probably ssh and proot-distro on the app, nothing else (not even pkg or apt)

@romanovj
Copy link

romanovj commented Jul 6, 2023

@RealEthanPlayzDev
what's the difference? just start fail safe session and run script in order to proot into termux environment

ofc you will need to change some lines

also, you can proot into anything, just unpack rootfs and write your own script

all you need is to patch proot binary with patchelf, and couple of libraries like here (I used this files in order to proot into homeassistant docker container from adb shell)

proot.zip

@RealEthanPlayzDev
Copy link

what's the difference? just start fail safe session and run script in order to proot into termux environment

@romanovj
/data/data/com.android.shell isn't accessible unless you're on adb, and I'm not fond with Android's internal structuring

@romanovj
Copy link

romanovj commented Jul 6, 2023

@RealEthanPlayzDev ofc you need to change path to whatever you have

@RealEthanPlayzDev
Copy link

RealEthanPlayzDev commented Jul 6, 2023

@romanovj

I've tried following that Reddit post's instructions along with changing the paths it needs, currently I'm stuck here:
Screenshot_20230706_161251_Termux
I've confirmed that libandroid-support.so does indeed exist within usr/lib

I believe talking about this here would be off-topic, do you have Discord perhaps?

@romanovj
Copy link

romanovj commented Jul 10, 2023

@agnostic-apollo what do you think about hexpatching?
/data/data/com.termux
to
/data/local/tmp/termu
or
/data/user/10/com.ter

I tried with /data/local/tmp/termu for adb and had no major problems. It's definitely easier than recompiling everything

@agnostic-apollo
Copy link
Member

Check #2734 for more generic solution for secondary users. It might be doable, but the prefix may also be used in other non binary files or in scripts and without the full /data/data/com.termux/files/* paths.

@segfault-bilibili
Copy link

segfault-bilibili commented Jul 11, 2023

I have a dumb idea about this issue. (I edited this message before being aware of #2734)

-TERMUX_BASE_DIR="/data/data/${TERMUX_APP_PACKAGE}/files"
-TERMUX_CACHE_DIR="/data/data/${TERMUX_APP_PACKAGE}/cache"
+TERMUX_BASE_DIR="/data/user/0/${TERMUX_APP_PACKAGE}/files/21473"
+TERMUX_CACHE_DIR="/data/user/0/${TERMUX_APP_PACKAGE}/cache"
 TERMUX_ANDROID_HOME="${TERMUX_BASE_DIR}/home"
 TERMUX_APPS_DIR="${TERMUX_BASE_DIR}/apps"
 TERMUX_PREFIX="${TERMUX_BASE_DIR}/usr"

When in bootstrap or apt install, after unpacking/decompressing files, the unpacked files can be binary-patched, replacing /data/user/0/com.termux/files/21473 with actual userId, like /data/user/10/com.termux/files/2147.

Because binary-patch does not tolerate string length changes, 21474 21473 is meant for reserving some more bytes for actual userId which could be longer than 1-byte (like 0).

However it might not be trivial to handle cases like encoded/compressed text, or the string itself is in some multi-byte non-ASCII encoding. (ah there could be other situations like checksummed files etc, as mentioned in #2734)


As for what 21473 means, it's the maximum allowed userId, in other words, the (currently) longest possible userId.

I looked up Android source code and then found that Android OS defined MAX_USER_ID as:

    // We need to keep process uid within Integer.MAX_VALUE.
    @VisibleForTesting
    static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;

https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-13.0.0_r63/services/core/java/com/android/server/pm/UserManagerService.java#253

where Integer.MAX_VALUE is known to be 2147383647, and UserHandle.PER_USER_RANGE is defined to be:

    /**
     * @hide Range of uids allocated for a user.
     */
    @UnsupportedAppUsage
    public static final int PER_USER_RANGE = 100000;

https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-13.0.0_r63/core/java/android/os/UserHandle.java#46

Besides, the maximum allowed userId does not reach 21474, only 21473 is allowd:

    @GuardedBy("mUsersLock")
    private int scanNextAvailableIdLocked() {
        for (int i = MIN_USER_ID; i < MAX_USER_ID; i++) {
            if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
                return i;
            }
        }
        return -1;
    }

https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-13.0.0_r63/services/core/java/com/android/server/pm/UserManagerService.java#5505


It also seems somewhat hilarious that my Android 7 AVD actually threw out Error: java.lang.IllegalStateException: No user id available! when executing pm create-user test after userId had reached 21473.

@segfault-bilibili
Copy link

segfault-bilibili commented Jul 11, 2023

@agnostic-apollo Oh it seems that I'm not the first person who has once came up with similar idea.

However I actually tried /./././ and the wrapper shell script env shebang of npm does not seem to work. PS1 prompt also printed out all the lengthy path. Maybe realpath has something to do with this? I don't know.

Edit after reply: it's simply because of lack of execute permission. chmod +x ../usr/lib/node_modules/npm/bin/* fixes this.

@agnostic-apollo
Copy link
Member

agnostic-apollo commented Jul 11, 2023

  • Are other packages working?
  • What errors are you getting? ("does not seem to work" is not an error and nor can anyone suggest fixes based on it.
  • Are you exporting that in $PATH?
  • Are DT_RUNPATH entries being properly replaced? Exporting LD_LIBRARY_PATH may help.

https://stackoverflow.com/questions/13769141/can-i-change-rpath-in-an-already-compiled-binary

https://github.com/NixOS/patchelf

http://blog.tremily.us/posts/rpath/

You may not have understood the suggestion in #2734

Packages must be compiled with for example /data/data/com.termux//. and then path replaced with /data/user/10/com.termux so that both match length 24. To support all user ids would require more logic and thinking.

realpath will not care for /.

@segfault-bilibili
Copy link

segfault-bilibili commented Jul 11, 2023

Are other packages working?

Probably? at least node launched without problem. (without full path, without modifying PATH or any other environment variable)

What errors are you getting? ("does not seem to work" is not an error and nor can be anyone suggest fixes based on it.

Sorry I forgot to take a screenshot :-) I'm actually going to fix this myself.

Are you exporting that in $PATH?

I saw that the env shebang had full path. I copied it and it executed (all inside Termux, not adb), listing all environment variables.

Are DT_RUNPATH entries being properly replaced?

realpath will not care for /.

I haven't done any binary patch so far. I just changed the TERMUX_PREFIX into some longer supposed-to-be-equivalent path like /data/data/././././com.termux/files/usr when building packages. I see that realpath does remove the redundant ./././. part therefore I made that guess. Removing that part might break some simple string comparison I think.

@segfault-bilibili
Copy link

segfault-bilibili commented Jul 11, 2023

To support all user ids would require more logic and thinking.

(1) I think TERMUX_PREFIX may have occurrences in many places, not just limited to RPATH. Therefore my idea is very simple & stupid: (during bootstrap or apt install) just search and replace all occurrences, regardless it's occurred in RPATH, shebang, vimrc or anything else. (however I haven't implemented anything to achieve this yet)

(2) I have just made some commits (based on a77e598) which reflect this your point, although it has not caught everything yet: https://github.com/segfault-bilibili/termux-packages/tree/20230711-deal-with-multiuser

(3) Even after doing massive string replace above (when doing build), I can still find related things like:

$ git grep data/data
disabled-packages/termux-x11/termux-x11.c:# define TERMUX_X11_DIR "/data/data/com.termux.x11/"
packages/coreutils/pwd.c.patch:+  if (true) /* Termux: Always try logical, to avoid permission denied on /data/data */
packages/dpkg/lib-dpkg-path-remove.c.patch:       '/data/data.dpkg-tmp'
packages/dpkg/lib-dpkg-path-remove.c.patch:       '/data/data/com.termux.dpkg-tmp'
packages/gpac/src-utils-os_divers.c.patch:      strcpy(szCacheDir, "/data/data/com.gpac.Osmo4/cache");
packages/wireguard-tools/build.sh:      $CC $CFLAGS $LDFLAGS -DWG_CONFIG_SEARCH_PATHS="\"$TERMUX_ANDROID_HOME/.wireguard $TERMUX_PREFIX/etc/wireguard /data/misc/wireguard /data/data/com.wireguard.android/files\"" -o wg-quick android.c

It's concerning that Termux-packaged executable may have references pointing to some outside dependencies, like /data/data/com.wireguard.android.

@segfault-bilibili
Copy link

segfault-bilibili commented Jul 11, 2023

I'm avoiding usage of equivalent path with redundant part like ././././, because (as said above) I guess this might break some simple string comparison, like [[ "$path1" == "/data/user/0/./././com.termux" ]] where path1 went through realpath but /data/user/0/./././com.termux didn't. However I think when the hardcoded path is pointing to somewhere outside Termux's data directory, there's probably no choice than adding redundant part.

@segfault-bilibili
Copy link

Ah sorry for posting replies before editing it carefully. I think I've done editing to clarify my points.

@segfault-bilibili
Copy link

@agnostic-apollo I've summarized my thoughts in this comment, the discussion around this idea might better continue in #2734 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests