From 3ca1478a3a6da5faf28f04587e13f8fcabb87b74 Mon Sep 17 00:00:00 2001 From: Nullptr <52071314+Dr-TSNG@users.noreply.github.com> Date: Sun, 3 Apr 2022 11:30:15 +0800 Subject: [PATCH] Optimize dex2oat wrapper (#1805) --- .../manager/ui/fragment/HomeFragment.java | 9 ++- app/src/main/res/values/strings.xml | 2 + .../lsposed/lspd/service/Dex2OatService.java | 34 +++++------ daemon/src/main/jni/CMakeLists.txt | 1 + daemon/src/main/jni/dex2oat.c | 31 ++++++++++ dex2oat/src/main/cpp/dex2oat.c | 18 ++++-- magisk-loader/magisk_module/customize.sh | 59 +++++++++++-------- magisk-loader/magisk_module/post-fs-data.sh | 8 --- 8 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 daemon/src/main/jni/dex2oat.c diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java index b01a3e29..a1f2e0ac 100644 --- a/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java +++ b/app/src/main/java/org/lsposed/manager/ui/fragment/HomeFragment.java @@ -120,8 +120,13 @@ public class HomeFragment extends BaseFragment { binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_inject_fail), HtmlCompat.FROM_HTML_MODE_LEGACY)); } if (!ConfigManager.dex2oatFlagsLoaded()) { - binding.warningTitle.setText(R.string.system_prop_incorrect_summary); - binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_prop_incorrect), HtmlCompat.FROM_HTML_MODE_LEGACY)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + binding.warningTitle.setText(R.string.dex2oat_service_crashed_summary); + binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.dex2oat_service_crashed), HtmlCompat.FROM_HTML_MODE_LEGACY)); + } else { + binding.warningTitle.setText(R.string.system_prop_incorrect_summary); + binding.warningSummary.setText(HtmlCompat.fromHtml(getString(R.string.system_prop_incorrect), HtmlCompat.FROM_HTML_MODE_LEGACY)); + } } } else { binding.warningCard.setVisibility(View.GONE); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c77ad0cc..31f72f50 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,6 +51,8 @@ Please report this to Magisk developer.]]> System Framework injection failed Magisk or some low-quality Magisk modules.
Please try to disable Magisk modules other than Riru and LSPosed or submit full log to developers.]]>
+ Dex optimizer service crashed + Modules may invalidate occasionally or applications may become laggy.]]> System prop incorrect Modules may invalidate occasionally.]]> Need to update diff --git a/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java b/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java index f4f01c05..edf70935 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java @@ -31,7 +31,6 @@ import android.util.Log; import java.io.File; import java.io.FileDescriptor; -import java.io.IOException; import java.io.InterruptedIOException; import java.nio.file.Files; import java.nio.file.Paths; @@ -44,22 +43,11 @@ public class Dex2OatService { private static final String DEX2OAT_64 = "/apex/com.android.art/bin/dex2oat64"; private Thread thread = null; + private LocalSocket serverSocket = null; + private LocalServerSocket server = null; + private FileDescriptor stockFd32 = null, stockFd64 = null; public void start() { - try { - var devPath = Files.readAllLines(Paths.get("/data/adb/lspd/dev_path")).get(0); - Log.d(TAG, "dev path: " + devPath); - daemon(devPath); - } catch (IOException e) { - Log.e(TAG, "dex2oat daemon failed to start", e); - } - } - - public boolean isAlive() { - return thread.isAlive(); - } - - private void daemon(String devPath) { thread = new Thread(() -> { try { Log.i(TAG, "dex2oat daemon start"); @@ -68,14 +56,18 @@ public class Dex2OatService { } else { Log.e(TAG, "failed to set socket context"); } + var devPath = getDevPath(); var sockPath = devPath + "/dex2oat.sock"; - var serverSocket = new LocalSocket(LocalSocket.SOCKET_STREAM); + Files.createDirectories(Paths.get(devPath)); + Log.d(TAG, "dev path: " + devPath); + + serverSocket = new LocalSocket(LocalSocket.SOCKET_STREAM); serverSocket.bind(new LocalSocketAddress(sockPath, LocalSocketAddress.Namespace.FILESYSTEM)); - var server = new LocalServerSocket(serverSocket.getFileDescriptor()); + server = new LocalServerSocket(serverSocket.getFileDescriptor()); SELinux.setFileContext(sockPath, "u:object_r:magisk_file:s0"); - FileDescriptor stockFd32 = null, stockFd64 = null; if (new File(DEX2OAT_32).exists()) stockFd32 = Os.open(DEX2OAT_32, OsConstants.O_RDONLY, 0); if (new File(DEX2OAT_64).exists()) stockFd64 = Os.open(DEX2OAT_64, OsConstants.O_RDONLY, 0); + while (true) { var client = server.accept(); try (var is = client.getInputStream(); @@ -94,6 +86,12 @@ public class Dex2OatService { thread.start(); } + public boolean isAlive() { + return thread.isAlive(); + } + + private static native String getDevPath(); + private boolean setSocketCreateContext(String context) { FileDescriptor fd = null; try { diff --git a/daemon/src/main/jni/CMakeLists.txt b/daemon/src/main/jni/CMakeLists.txt index 046ef8d3..8ff0318a 100644 --- a/daemon/src/main/jni/CMakeLists.txt +++ b/daemon/src/main/jni/CMakeLists.txt @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.4.1) add_subdirectory(${EXTERNAL_ROOT} external) set(SOURCES + dex2oat.c logcat.cpp obfuscation.cpp ) diff --git a/daemon/src/main/jni/dex2oat.c b/daemon/src/main/jni/dex2oat.c new file mode 100644 index 00000000..2d603415 --- /dev/null +++ b/daemon/src/main/jni/dex2oat.c @@ -0,0 +1,31 @@ +/* + * This file is part of LSPosed. + * + * LSPosed is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LSPosed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LSPosed. If not, see . + * + * Copyright (C) 2022 LSPosed Contributors + */ + +// +// Created by Nullptr on 2022/4/2. +// + +#include + +char kTmpDir[] = "placeholder_/dev/0123456789abcdef"; + +JNIEXPORT jstring JNICALL +Java_org_lsposed_lspd_service_Dex2OatService_getDevPath(JNIEnv *env, jclass clazz) { + return (*env)->NewStringUTF(env, kTmpDir + 12); +} diff --git a/dex2oat/src/main/cpp/dex2oat.c b/dex2oat/src/main/cpp/dex2oat.c index 121dc68c..67c97d9e 100644 --- a/dex2oat/src/main/cpp/dex2oat.c +++ b/dex2oat/src/main/cpp/dex2oat.c @@ -72,11 +72,6 @@ static void *recv_fds(int sockfd, char *cmsgbuf, size_t bufsz, int cnt) { return CMSG_DATA(cmsg); } -static void write_int(int fd, int val) { - if (fd < 0) return; - write(fd, &val, sizeof(val)); -} - static int recv_fd(int sockfd) { char cmsgbuf[CMSG_SPACE(sizeof(int))]; @@ -89,6 +84,18 @@ static int recv_fd(int sockfd) { return result; } +static int read_int(int fd) { + int val; + if (read(fd, &val, sizeof(val)) != sizeof(val)) + return -1; + return val; +} + +static void write_int(int fd, int val) { + if (fd < 0) return; + write(fd, &val, sizeof(val)); +} + int main(int argc, char **argv) { LOGI("dex2oat wrapper"); struct sockaddr_un sock; @@ -101,6 +108,7 @@ int main(int argc, char **argv) { } write_int(sock_fd, LP_SELECT(32, 64)); int stock_fd = recv_fd(sock_fd); + read_int(sock_fd); close(sock_fd); LOGD("sock: %s %d", sock.sun_path, stock_fd); diff --git a/magisk-loader/magisk_module/customize.sh b/magisk-loader/magisk_module/customize.sh index bec3cc6b..d0a8d3d9 100644 --- a/magisk-loader/magisk_module/customize.sh +++ b/magisk-loader/magisk_module/customize.sh @@ -88,31 +88,6 @@ extract "$ZIPFILE" 'daemon' "$MODPATH" rm -f /data/adb/lspd/manager.apk extract "$ZIPFILE" 'manager.apk' '/data/adb/lspd' -if [ "$API" -ge 29 ]; then - ui_print "- Extracting dex2oat binaries" - mkdir "$MODPATH/bin" - - if [ "$ARCH" = "arm" ] || [ "$ARCH" = "arm64" ]; then - extract "$ZIPFILE" "bin/armeabi-v7a/dex2oat" "$MODPATH/bin" true - mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat32" - - if [ "$IS64BIT" = true ]; then - extract "$ZIPFILE" "bin/arm64-v8a/dex2oat" "$MODPATH/bin" true - mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" - fi - elif [ "$ARCH" == "x86" ] || [ "$ARCH" == "x64" ]; then - extract "$ZIPFILE" "bin/x86/dex2oat" "$MODPATH/bin" true - mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat32" - - if [ "$IS64BIT" = true ]; then - extract "$ZIPFILE" "bin/x86_64/dex2oat" "$MODPATH/bin" true - mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" - fi - fi -else - extract "$ZIPFILE" 'system.prop' "$MODPATH" -fi - ui_print "- Extracting daemon libraries" if [ "$ARCH" = "arm" ] ; then extract "$ZIPFILE" 'lib/armeabi-v7a/libdaemon.so' "$MODPATH" true @@ -184,6 +159,40 @@ elif [ "$FLAVOR" == "riru" ]; then fi fi +if [ "$API" -ge 29 ]; then + ui_print "- Extracting dex2oat binaries" + mkdir "$MODPATH/bin" + + if [ "$ARCH" = "arm" ] || [ "$ARCH" = "arm64" ]; then + extract "$ZIPFILE" "bin/armeabi-v7a/dex2oat" "$MODPATH/bin" true + mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat32" + + if [ "$IS64BIT" = true ]; then + extract "$ZIPFILE" "bin/arm64-v8a/dex2oat" "$MODPATH/bin" true + mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" + fi + elif [ "$ARCH" == "x86" ] || [ "$ARCH" == "x64" ]; then + extract "$ZIPFILE" "bin/x86/dex2oat" "$MODPATH/bin" true + mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat32" + + if [ "$IS64BIT" = true ]; then + extract "$ZIPFILE" "bin/x86_64/dex2oat" "$MODPATH/bin" true + mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" + fi + fi + + ui_print "- Patching binaries" + DEV_PATH=$(tr -dc 'a-f0-9' < /dev/urandom | head -c 16) + while [ -d "/dev/$DEV_PATH" ]; do + DEV_PATH=$(tr -dc 'a-f0-9' < /dev/urandom | head -c 16) + done + sed -i "s/placeholder_\/dev\/................/placeholder_\/dev\/$DEV_PATH/" "$MODPATH/libdaemon.so" + sed -i "s/placeholder_\/dev\/................/placeholder_\/dev\/$DEV_PATH/" "$MODPATH/bin/dex2oat32" + sed -i "s/placeholder_\/dev\/................/placeholder_\/dev\/$DEV_PATH/" "$MODPATH/bin/dex2oat64" +else + extract "$ZIPFILE" 'system.prop' "$MODPATH" +fi + set_perm_recursive "$MODPATH" 0 0 0755 0644 set_perm_recursive "$MODPATH/bin" 0 0 0755 0755 u:object_r:dex2oat_exec:s0 chmod 0744 "$MODPATH/daemon" diff --git a/magisk-loader/magisk_module/post-fs-data.sh b/magisk-loader/magisk_module/post-fs-data.sh index 92fce217..c26cb98f 100644 --- a/magisk-loader/magisk_module/post-fs-data.sh +++ b/magisk-loader/magisk_module/post-fs-data.sh @@ -25,14 +25,6 @@ rm -f "/data/local/tmp/daemon.apk" cd "$MODDIR" if [ "$(getprop ro.build.version.sdk)" -ge 29 ]; then - TMP=$($RANDOM | md5sum | head -c 16) - while [ -d "/dev/$TMP" ]; do - TMP=$($RANDOM | md5sum | head -c 16) - done - mkdir "/dev/$TMP" - echo "/dev/$TMP" > "/data/adb/lspd/dev_path" - sed -i "s/placeholder_\/dev\/................/placeholder_\/dev\/$TMP/" "$MODDIR/bin/dex2oat32" - sed -i "s/placeholder_\/dev\/................/placeholder_\/dev\/$TMP/" "$MODDIR/bin/dex2oat64" mount --bind "$MAGISK_PATH/.magisk/modules/$MODNAME/bin/dex2oat32" "/apex/com.android.art/bin/dex2oat32" mount --bind "$MAGISK_PATH/.magisk/modules/$MODNAME/bin/dex2oat64" "/apex/com.android.art/bin/dex2oat64" fi