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

[Bug]: Dynamically loaded apk/dex files like termux-am package am.apk file must be read only on Android 14 #16255

Closed
agnostic-apollo opened this issue Apr 17, 2023 · 2 comments
Labels
android-14 bug report Something is not working properly inactive No activity in a certain period of time

Comments

@agnostic-apollo
Copy link
Member

Problem description

Android 14 requires that all dynamically loaded dex files are read-only to prevent security issues.

Running am triggers following exception and SIGABRT. This wold affect other apk files being loaded by users. Maybe termux-x11 starter apk or something too if being used @twaik.

https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading

https://github.com/termux/TermuxAm/

Ljava/lang/ClassLoader$SystemClassLoader; failed initialization: java.lang.SecurityException: Writable dex file '/data/data/com.termux/files/usr/libexec/termux-am/am.apk' is not allowed.
                   at java.lang.Object dalvik.system.DexFile.openDexFileNative(java.lang.String, java.lang.String, int, java.lang.ClassLoader, dalvik.system.DexPathList$Element[]) (DexFile.java:-2)
                   at java.lang.Object dalvik.system.DexFile.openDexFile(java.lang.String, java.lang.String, int, java.lang.ClassLoader, dalvik.system.DexPathList$Element[]) (DexFile.java:406)
                   at void dalvik.system.DexFile.<init>(java.lang.String, java.lang.ClassLoader, dalvik.system.DexPathList$Element[]) (DexFile.java:128)
                   at void dalvik.system.DexFile.<init>(java.io.File, java.lang.ClassLoader, dalvik.system.DexPathList$Element[]) (DexFile.java:101)
                   at dalvik.system.DexFile dalvik.system.DexPathList.loadDexFile(java.io.File, java.io.File, java.lang.ClassLoader, dalvik.system.DexPathList$Element[]) (DexPathList.java:438)
                   at dalvik.system.DexPathList$Element[] dalvik.system.DexPathList.makeDexElements(java.util.List, java.io.File, java.util.List, java.lang.ClassLoader, boolean) (DexPathList.java:397)
                   at void dalvik.system.DexPathList.<init>(java.lang.ClassLoader, java.lang.String, java.lang.String, java.io.File, boolean) (DexPathList.java:166)
                   at void dalvik.system.BaseDexClassLoader.<init>(java.lang.String, java.lang.String, java.lang.ClassLoader, java.lang.ClassLoader[], java.lang.ClassLoader[], boolean) (BaseDexClassLoader.java:160)
                   at void dalvik.system.BaseDexClassLoader.<init>(java.lang.String, java.io.File, java.lang.String, java.lang.ClassLoader) (BaseDexClassLoader.java:105)
                   at void dalvik.system.PathClassLoader.<init>(java.lang.String, java.lang.String, java.lang.ClassLoader) (PathClassLoader.java:71)
                   at java.lang.ClassLoader java.lang.ClassLoader.createSystemClassLoader() (ClassLoader.java:224)
                   at java.lang.ClassLoader java.lang.ClassLoader.-$$Nest$smcreateSystemClassLoader() (ClassLoader.java:-1)
                   at void java.lang.ClassLoader$SystemClassLoader.<clinit>() (ClassLoader.java:183)
                   at java.lang.ClassLoader java.lang.ClassLoader.getSystemClassLoader() (ClassLoader.java:1098)
Cmdline: /system/bin/app_process / com.termux.termuxam.Am --help
pid: 7004, tid: 7004, name: main  >>> /system/bin/app_process <<<
uid: 10169
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: 'Check failed: system_class_loader != nullptr '

The /data/data/com.termux/files/usr/libexec/termux-am/am.apk files needs to have 400 (r-- --- ---) permission. Setting permissions in termux_step_make_install should probably work. If someone fixes it and provides a build, I can test.

termux_step_make_install() {
cp $TERMUX_PKG_SRCDIR/am-libexec-packaged $TERMUX_PREFIX/bin/am
mkdir -p $TERMUX_PREFIX/libexec/termux-am
cp $TERMUX_PKG_SRCDIR/app/build/outputs/apk/release/app-release-unsigned.apk $TERMUX_PREFIX/libexec/termux-am/am.apk
}

What steps will reproduce the bug?

Any $PREFIX/bin/am command.

What is the expected behavior?

No response

System information

termux-info:

Android 14
@agnostic-apollo agnostic-apollo added bug report Something is not working properly untriaged and removed untriaged labels Apr 17, 2023
@twaik
Copy link
Member

twaik commented Apr 17, 2023

It looks like dalvik simply checks if file is writable. Source. Does apt set permissions on files after unpacking them? I mean on termux, not upstream.

@agnostic-apollo
Copy link
Member Author

agnostic-apollo commented Apr 17, 2023

It looks like dalvik simply checks if file is writable

Yeah, I already checked. chmod -w works.

Does apt set permissions on files after unpacking them?

It shouldn't. dpkg doesn't as far as my tests for debs with termux-create-package go. The deb file permissions should persist but it seems like the write bit must be set for all the files in the deb, otherwise dpkg reports Unable to open '/path/to/extraction': Permission denied. I guess postinst will need to be used to remove the write bit. If file already exists at extraction path without the write bit set, dpkg still succeeds in installing the package, so shouldn't need to use preinst to set write bit as normally overwrite would fail. Issue seems to be only if file in deb does not have write bit set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android-14 bug report Something is not working properly inactive No activity in a certain period of time
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants