Closed ghost closed 2 years ago
Maybe try adding android:allowNativeHeapPointerTagging="false"
to AndroidManifest.xml
of termux-app
, as per https://source.android.com/devices/tech/debug/tagged-pointers. Although it mentions it only works with targetSdkVersion
30
, but don't see any checks in AOSP from a quick look, but at least should work on android 12 with targetSdkVersion
30
.
The logic for decision has changed in android 11
r40
vs master
as per https://cs.android.com/android/_/android/platform/frameworks/base/+/15cce113f7232e117b091770c220ebc1b55f41d2 even though master
is also 11
.
I wrote up why this was happening with Swift on the Swift forums in May: the issue is that Swift sets its own tag in the top byte and that collides with Android's system tagging. Presumably something similar is happening with OpenJDK.
It appears that hardware support for memory tagging will only roll out with the new ARMv9 CPUs in the next year, but that link does mention "Software support for using MTE is being introduced as part of Android 12."
Maybe Android 12 will require software tagging, even though most hardware that is still ARMv8 doesn't natively support it yet, to get everyone to update any software that uses its own tag in the top byte, causing collisions. In our case, that only appears to be these three packages, so not much?
I just upgraded to Android 12 and have no problem with tagged pointers. Maybe this will only be a requirement for new devices that ship with Android 12 from now on.
Seems to work fine for me on my s21 ultra running android 12
Seems to work fine for me on my s21 ultra running android 12
That shipped last year with Android 11 though, right? As I noted above, they're not requiring devices that upgrade to Android 12 to enable MTE, though they may be doing so for new devices that ship with Android 12, like the recently released Pixel 6, for all we know.
Oh sorry my bad in that case I hope this gets fixed by time I buy a new phone
I asked and was told that the Android team has decided to reserve the entire top byte on pointers in AArch64 devices, android/ndk#1653, which is apparently being slowly rolled out starting with Android 11. I'm working on a patch for Swift, where the runtime has always set the top bit on pointers to determine whether to reference-count them or not, to account for this Android change.
Is there any workaround for this at the moment? I'm running Termux on my Galaxy Tab S7, which got updated to Android 12 recently... And I'd really want to run Java on there.
@MonsterDruide1, was it working fine with Android 11 on your Tab S7 before?
I updated my tablet about half an hour before trying to use Java, so I'm not sure if it would have worked. The update has been published very recently by Samsung and upgrades to OneUI 4.0, but I'm not even sure anymore whether it had Android 11 or 12 before that specific update.
OK, was wondering if they switched tagged pointers on with the update... guess we'll never know. It appears that OpenJDK uses its own pointer tags that collides with Android's new memory tagging: I'm unaware of any JDK workaround other than rebuilding Termux yourself with the tagging flag turned off, as mentioned above.
Okay, but that definitely already is a workaround I can try. Thanks for the quick response, and I'll report on whether it works later!
No, this doesn't seem to work. I've added android::allowNativeHeapPointerTagging="false"
in line 38 of the AndroidManifest, and as Android Studio complained about it, afterwards also tried increasing minimum and target SDK to 30
in gradle.properties
. No change, it also crashes when just running javac
, halfway through the help message.
I notice that you pasted two colons in that flag here, while every other flag uses one?
Oops, that was just a typo in the comment here. It is properly written with a single colon in Android Studio.
Note, I've also tried upgrading the NDK version. There seem to be more issues with lifting the compile, target and minimum SDK to 31, but it's still crashing with them being at 30
.
Also, maybe an important thing:
It seems to be luck-based whether javac
without options finishes printing the help message or if it gets canceled by Android before. Sometimes it shows all of the help message lines with no issues and no Aborted
message, sometimes it gets interrupted halfway through, but always after the line of -profile <profile>
.
Ummm, just curious, which branch of termux-app
are you using to test? Bumping targetSdkVersion
in master
should result in execution failure for any binary from app data directory unless its a symlink from apk native directory or selinux policy is patched.
I'm using master
... which one should I test instead?
I am assuming that it worked because you upgraded an app from an older targetSdkVersion
and android 10 restrictions didn't engage, maybe same reason android:allowNativeHeapPointerTagging
didn't work. Uninstall and reinstall app with targetSdkVersion
30
.
https://github.com/termux/termux-packages/wiki/Termux-and-Android-10
But if you were to bump version, even login shell would fail, you would need use updated-flavor
branch and create bootstrap zip with openjdk-17
in it, since if its download from apt
repo, it won't execute. The branch and generate-bootstrap
would need some patches, since old now, and --android10
flag needs to be passed too to script.
https://github.com/termux/termux-packages/wiki/Termux-and-Android-10
Well, I only upgraded the version because Android Studio told me that the option is useless on most versions. If this is not necessary, I'd avoid going through all of the extra building steps, as it seems that would keep my installation more flexible to post-installing other packages.
Is it possible to enable this flag effectively while not packaging all required packages into installation beforehand?
Uninstalling and fully cleaning/reconfiguring the project with targetSdkVersion = 30
broke already the login shell: Permission denied for accessing the login executable. I cannot use the workaround listed in the links above (SELinux permissions), as the device is not rooted.
Do I really need to bump the version to enable the flag in the manifest, or can it also somehow be not ignored in the older targetSdkVersion
?
According to their official explanation linked above,
As such, applications that use targetSdkLevel < 30 will not have pointer tagging enabled by default. We also provide an escape hatch for applications built with targetSdkLevel >= 30 to ease the transitional period.
So maybe they changed the default for even when you target API 28 and the only way to override that is by targeting API 30 and using the new flag. Are you building from the updated-flavor
branch now as he said you'd have to?
No, I only continued trying master
, as I understood it that switching the branch would only be required if bumping the version is absolutely necessary.
I've now tried building from updated-flavor
, but I can't seem to get openjdk-17
to work. I've built the bootstrap in a WSL using scripts/generate-bootstraps.sh --android10 -a openjdk-17
, but I can't run javac
or pkg in openjdk-17
, both resulting in an error (No command javac found
vs. Unable to locate package openjdk-17
).
Do I really need to bump the version to enable the flag in the manifest, or can it also somehow be not ignored in the older targetSdkVersion?
Possibly yes, since that's what the official doc says, but I couldn't find any checks in my quick search. They could be in native code.
but I can't run javac
Does the bootstrap zip created contain javac
? Was it successfully added to apk, did u add return statement in downloadBootstrap()
as mentioned in https://github.com/termux/termux-app/issues/1983#issuecomment-812965326
What does stat $PREFIX/bin/javac
show? Symlink could be an issue too, maybe, since it may be relative to apk native dir.
$ stat $PREFIX/bin/javac
File: /data/data/com.termux/files/usr/bin/javac -> ../opt/openjdk/bin/javac
Size: 24 Blocks: 0 IO Block: 4096 symbolic link
$ stat $PREFIX/opt/openjdk/bin/javac
File: /data/data/com.termux/files/usr/opt/openjdk/bin/javac
Size: 8264 Blocks: 24 IO Block: 4096 regular file
Okay, then I'll continue testing on the bumped version using the separate branch.
I manually checked the bootstrap zip files, they contained openjdk
in the /opt
-directory, and an entry in the SYMLINKS.txt
about it.
I disabled the replacement of official bootstrap files by commenting the lines invoking downloadBootstrap
, should have the same effect as immediately returning from in there.
Both stat
-commands give a File not found.
for me.
Both
stat
-commands give aFile not found.
for me.
Check the bootstrap in the built apk, it should be in the lib directory.
Then check logcat for which files are added.
The android 10 installation is done by https://github.com/termux/termux-app/blob/60f07718880bdd8d241f3c13126343b0b406c818/app/src/updated/java/com/termux/app/TermuxPackageInstaller.java#L48
Add any debug log entries if needed.
You also need to disable legacy TermuxInstaller
.
https://github.com/termux/termux-app/discussions/2441#discussioncomment-1733940
OpenJDK files are in $PREFIX/opt/
.
OpenJDK files are in
$PREFIX/opt/
.
Already told him that.
$ stat $PREFIX/opt/openjdk/bin/javac
...
I've updated the issue, as it is really related to Android 12 rather than 11 where tagged pointers switch was working.
Check the bootstrap in the built apk, it should be in the lib directory.
They are .so
files, so I'm unsure of how to verify that OpenJDK has been added there, but with ~22MB size that's definitely not enough. Java is a lot bigger than that, the zipped bootstraps have a size of ~210MB each.
Nevermind, after a few more tweaks to the gradle file it has gone up to 220 MB each. However, the stat
commands still only show No such file or directory
.
Nevermind the nevermind, another uninstall and reinstall later it showed .../bin/javac: Permission denied
on trying to execute javac
. A chmod +x
later, it shows CANNOT LINK EXECUTABLE "javac": library "libc++_shared.so" not found: needed by .../lib/libandroid-spawn.so in namespace (default)
.
Then check logcat for which files are added.
I guess this doesn't matter by now, since that problem has been resolved?
The android 10 installation is done by https://github.com/termux/termux-app/blob/60f07718880bdd8d241f3c13126343b0b406c818/app/src/updated/java/com/termux/app/TermuxPackageInstaller.java#L48
I can't even find that file in Android Studio. With src/updated/java
it is in a non-standard directory, and I guess it's not even included in the apk
?
You also need to disable legacy
TermuxInstaller
. termux/termux-app#2441 (reply in thread)
I'm not sure what the best way to do that is. I've now tried commenting out the contents of all functions in TermuxInstaller
. However, doing that broke everything, with the app now just showing a black screen. There is no obvious error message in the console, and the only two semi-useful entries are
2022-01-21 10:16:44.969 16634-16634/? E/USNET: USNET: appName: com.termux
2022-01-21 10:16:44.971 16634-16634/? D/ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument
With src/updated/java it is in a non-standard directory, and I guess it's not even included in the apk?
This is configured through productFlavors
in build.gradle.
Yeah, what xeffyr says and src/updated/java
will be included if you build updated
flavor.
https://developer.android.com/studio/build/build-variants#product-flavors
They are .so files, so I'm unsure of how to verify that OpenJDK has been added there There are
.so
files, but a mapping
Check libfiles.so
I'm not sure what the best way to do that is. I've now tried commenting out the contents of all functions in TermuxInstaller.
Only keep code inside the setupBootstrapIfNeeded()
lamda without calling it.
Once built, do send both stat
outputs.
Yeah, what xeffyr says and
src/updated/java
will be included if you buildupdated
flavor. https://developer.android.com/studio/build/build-variants#product-flavors
Ah, I needed to change the build variant there. I had no idea this was even possible, but it should now build the correct flavor.
Check
libfiles.so
Yes, but how can I actually see the "inside" of .so
files?
Only keep code inside the
setupBootstrapIfNeeded()
lamda without calling it.
Okay, that worked. Thanks for attaching the line.
Once built, do send both
stat
outputs.
Now I'm back at another problem: sh: javac: inaccessible or not found
. In fact, even sh
does not work, with the same error. That looks like a really messed-up environment... what's the matter here?
Also, is there any way to get the bootstrap externalized from the APK? Building the apk takes sooo absurdly long with the basic bootstrap + openjdk-17
and build-essentials
...
Yes, but how can I actually see the "inside" of
.so
files?
The libfiles.so
should contain mapping of lib names to their real symlink that will be done in $PREFIX
. The lib directory in the apk should contain the files, you can extract them.
Did u reinstall apk? For changes in bootstrap to take place, you need to have a fresh install. Installation is only done once.
Also, is there any way to get the bootstrap externalized from the APK?
The whole point of updated flavor branch is so that all binaries exist inside the apk, otherwise execution isn't allowed by android. Welcome to the wannabe-security-android-design.
The sh
under $PREFIX
is for dash
shell. You need to call /system/bin/sh
and likely set LD_LIBRARY_PATH
to /system/lib64
. It's execution will be allowed for all cases, but dash
only if its inside apk.
The
libfiles.so
should contain mapping of lib names to their real symlink that will be done in$PREFIX
. The lib directory in the apk should contain the files, you can extract them.
Ohh, wait a second, there is no libfiles.so
! There are only libtermux.so
and the bootstrap-library. I think it's something about my gradle, where I just randomly changed things so far until it looked right to me, which is most likely wrong...
What would be the right setup here? I'm now trying to remove all the contents of downloadBootstrap
, replacing them with just a call to expandBootstrap
(which seems to be responsible for creating the .so
above?). Let's see if that works.
Did u reinstall apk? For changes in bootstrap to take place, you need to have a fresh install. Installation is only done once.
Yes, I'm uninstalling after every attempt, and I'm doing a full clean rebuild of gradle after each change to either gradle files or bootstrap zips.
The whole point of updated flavor branch is so that all binaries exist inside the apk, otherwise execution isn't allowed by android. Welcome to the wannabe-security-android-design.
Oh. That's bad. Why would they even want to do that? If the developers of some app want to run malicious code, they can surely do that from within the apk
file. No need for external code there, and I have no idea what else they would block with that. But that discussion is probably outside the scope of this issue.
The
sh
under$PREFIX
is fordash
shell. You need to call/system/bin/sh
and likely setLD_LIBRARY_PATH
to/system/lib64
. It's execution will be allowed for all cases, butdash
only if its inside apk.
I didn't really understand a lot of what you said there, I'm not too experienced with Linux... all I can say is that LD_LIBRARY_PATH
is empty (echo $LD_LIBRARY_PATH
= nothing). It's not important for me to run the shell, I just noted that javac
did not work and tried sh
for context... which also didn't work, so it's not a openjdk-specific issue.
I'm currently building for the simplified, updated gradle file, let's see if it works with that one. That would be
def downloadBootstrap(String arch, String expectedChecksum, String version, boolean isPackagesInApk) {
def file = new File(projectDir, "src/main/cpp/bootstrap-" + arch + ".zip");
expandBootstrap(file, expectedChecksum, arch)
return
}
First you need to ensure you are building the updated
flavor. Second you need to ensure your custom bootstrap gets added to apk instead of downloaded bootstrap. I am currently on mobile, so can't (harder to) review the code. You need to disable overwrite of custom bootstrap.
That would be
Yeah, should work.
If the developers of some app want to run malicious code, they can surely do that from within the apk file.
Pretty much, apks built on dev devices or servers already violate W^X. But yeah, off topic.
If you run sh
, it will run $PREFIX/bin/sh
(dash
), not /system/bin/sh
. PATH
does not have /system/bin
in termux by default. Exec restrictions do not apply to system binaries and only to binaries in app data.
FYI, for PATH and LD_LIBRARY_PATH, check https://github.com/agnostic-apollo/tudo#path-and-ld_library_path-priorities
Check
libfiles.so
Okay, there are now a LOT more .so
files in that directory than before (13,319 vs. 2). libfiles.so
contains javac:
lib6415.so?opt/openjdk/man/man1/javac.1.gz
lib6639.so?opt/openjdk/bin/javac
However, invoking stat
is impossible due to sh: stat: inaccessible or not found
.
It seems like the encoding of ←
did not work properly... any way to fix that?
It seems like the encoding of ← did not work properly... any way to fix that?
API>28 build is here offtopic but your "←" problem is known to me and was resolved with a workaround. This belongs more to *app
and not *packages
and your problem is especially belonging to API=31.
there are now a LOT more
.so
files in that directory than before (n=13319
vs. 2).libfiles.so
The idea of branches update flavor
and android 10
(both far away from master
) is to save all files from u=~../usr
in:
nl=~/../../lib
and connect by symlinks to $u
. Your n
is find $u -type f
. The branches does not distinguish whether this is necessary (only elf-files) for API>28 and all files can no longer be edited in Termux except by rebuild.
Pointer tag for 0x6f43493930 was truncated, see 'https://source.android.com/devices/tech/debug/tagged-pointers'. Aborted
Receiving this error after upgrading to Android 12 and using OpenJDK 17
If you just want to run java and don't care about performance, you only need to get a 32 bit java installation. Tagged pointers are entirely a 64-bit thing, so 32-bit java is completely unaffected.
As a proof of concept, I modified the termux apk, removed the arm64 library and re-signed. After reinstalling the app, I get a pure 32 bit shell. Now I can use java in Android 12.
Here's my modified apk, if you're interested:
termux_arm32_118.apk.zip (You don't need it. You can download termux-app_v0.118.0+github-debug_armeabi-v7a.apk
here.)
Note that you need to uninstall the original termux to install it, your data will be lost.
There is obviously a better way to install it, but it's also more complicated (termux's openjdk-17:arm
has too many dependencies and conflicts with 64-bit packages). The method mentioned above is the fastest.
FYI, termux github builds are also supplied as arch specific so no need to modify apk.
have a hack way to use OpenJDK in Android 12,like this but no need install 32bit Termux,just download 32bit OpenJDK deb file from Termux repo and extract deb file resource,then set JAVA_HOME env, using LD_LIBRARY_PATH=$JAVA_HOME/lib $JAVA_HOME/bin/java
to run java,you will get some error ,read the error message ,then go to Termux repo download the corresponding 32bit lib file, move it to $JAVA_HOME/lib.
If you just want to run java and don't care about performance, you only need to get a 32 bit java installation. Tagged pointers are entirely a 64-bit thing, so 32-bit java is completely unaffected.
As a proof of concept, I modified the termux apk, removed the arm64 library and re-signed. After reinstalling the app, I get a pure 32 bit shell. Now I can use java in Android 12.
Here's my modified apk, if you're interested: termux_arm32_118.apk.zip
Note that you need to uninstall the original termux to install it, your data will be lost.
There is obviously a better way to install it, but it's also more complicated (termux's openjdk-17 has too many dependencies and conflicts with 64-bit packages). The method mentioned above is the fastest.
have a hack way to use OpenJDK in Android 12,like this but no need install 32bit Termux,just download 32bit OpenJDK deb file from Termux repo and extract deb file resource,then set JAVA_HOME env, using
LD_LIBRARY_PATH=$JAVA_HOME/lib $JAVA_HOME/bin/java
to run java,you will get some error ,read the error message ,then go to Termux repo download the corresponding 32bit lib file, move it to $JAVA_HOME/lib.
From: https://hu60.cn/q.php/bbs.topic.102531.html (zhCN)
# View current package architecture
dpkg --print-architecture
# Add 32-bit arm architecture
dpkg --add-architecture arm
# show the added architecture
dpkg --print-foreign-architectures
# update package list
apt update
# Create and enter the deb folder
mkdir ~/deb
cd ~/deb
# Download `openjdk-17:arm`
apt download openjdk-17:arm
# Download all dependencies of `openjdk-17:arm`
LANG=en LANGUAGE=en apt-cache depends --recurse openjdk-17:arm | grep -E '(Depends|PreDepends|Recommends|Suggests):' | awk '{print $2}' | grep -v '<' | xargs apt download
# Create and enter the termux32 folder
mkdir ~/../termux32
cd ~/../termux32
# extract debs
find ~/deb/ -type f | while read f; do dpkg -X "$f" ~/../termux32; done
# Set a PREFIX32 environment variable
PREFIX32="$(realpath ~/../termux32/data/data/com.termux/files/usr)"
# Create a symlink for the deep directory
ln -s "$PREFIX32" ~/../usr32
# Create a wrapper for 32-bit programs
PREFIX32="$(realpath ~/../usr32)"
cat >"$PREFIX/bin/bin32_wrapper" <<EOF
#!$PREFIX/bin/sh
bin="\$(basename "\$0")"
export PREFIX="$PREFIX32"
export JAVA_HOME="\$PREFIX/opt/openjdk"
export PATH="\$PREFIX/bin:\$JAVA_HOME/bin"
export LD_LIBRARY_PATH="\$PREFIX/lib:\$JAVA_HOME/lib"
exec "\$PREFIX/bin/\$bin" "\$@"
EOF
# give execute permission
chmod +x "$PREFIX/bin/bin32_wrapper"
# Create wrapper link for 32-bit java
cd "$PREFIX/bin"
ls ~/../usr32/opt/openjdk/bin | while read f; do echo "$f"; ln -s bin32_wrapper "$f"; done
# Create a test java file
mkdir ~/java
cd ~/java
cat >./HelloWorld.java <<EOF
public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World!");
}
}
EOF
# compile it
javac HelloWorld.java
# run it
java HelloWorld
It would be better to wrap the actual $JAVA_HOME/bin/*
binaries. Programs like gradlew
execute this directly instead of searching $PATH
.
tagged pointers
for Android 12 & 11I don't understand what the problem is, this has been known for over a year and no one has yet decided to create a patch to fix this?
I don't understand what the problem is, this has been known for over a year and no one has yet decided to create a patch to fix this?
Feel free to open a PR if you know how to fix it.
I don't understand what the problem is, this has been known for over a year and no one has yet decided to create a patch to fix this?
Feel free to open a PR if you know how to fix it.
Seems like this is the fix, #7332 (comment)
Sure, you can follow those instructions as a workaround (easy to do on affected devices), but a fix would preferably fix the root cause as done for swift.
If you need OpenJDK in Termux - do not upgrade to Android 12.
Problem description
After upgrading to Android 12, workaround for tagged pointers in package
openjdk-17
is not working anymore.This means we will need to either wait fixes on upstream or fix broken packages manually which may require quite much effort, depending on codebase size.
Other packages known to be affected by issue with tagged pointers:
swift
- https://github.com/termux/termux-packages/issues/6261st
from x11-packages - https://github.com/termux/x11-packages/issues/407What steps will reproduce the bug?
pkg upgrade && pkg install openjdk-17
javac
without arguments or attempt to compile something.System information
termux-info: