diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java index 8aa08002..9ca7606c 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java @@ -1,5 +1,9 @@ package com.elderdrivers.riru.edxp.framework; +import com.elderdrivers.riru.edxp.util.Utils; + +import de.robv.android.xposed.XposedHelpers; + public class Zygote { // prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote @@ -8,4 +12,12 @@ public class Zygote { public static native void reopenFilesAfterFork(); + public static void allowFileAcrossFork(String path) { + try { + Class zygote = XposedHelpers.findClass("com.android.internal.os.Zygote", null); + XposedHelpers.callStaticMethod(zygote, "nativeAllowFileAcrossFork", path); + } catch (Throwable throwable) { + Utils.logE("error when allowFileAcrossFork", throwable); + } + } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java index 7abfa1ff..88bd5a11 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java @@ -4,7 +4,6 @@ import android.text.TextUtils; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; import com.elderdrivers.riru.edxp.util.ProcessUtils; import com.elderdrivers.riru.edxp.util.Utils; @@ -87,16 +86,12 @@ public class BlackWhiteListProxy extends BaseProxy { // loadModules once for all child processes of zygote // TODO maybe just save initZygote callbacks and call them when whitelisted process forked? mRouter.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); } private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { ConfigManager.appDataDir = appDataDir; ConfigManager.niceName = niceName; final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (!isDynamicModulesMode) { - Zygote.reopenFilesAfterFork(); - } mRouter.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java index 68c46233..c28ff453 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java @@ -2,7 +2,6 @@ package com.elderdrivers.riru.edxp.proxy; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; @@ -27,7 +26,6 @@ public class NormalProxy extends BaseProxy { mRouter.installBootstrapHooks(false); // only load modules for secondary zygote mRouter.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); } public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { @@ -35,7 +33,6 @@ public class NormalProxy extends BaseProxy { ConfigManager.appDataDir = appDataDir; ConfigManager.niceName = niceName; mRouter.prepare(false); - Zygote.reopenFilesAfterFork(); mRouter.onEnterChildProcess(); // load modules for each app process on its forked if dynamic modules mode is on mRouter.loadModulesSafely(false); @@ -57,7 +54,6 @@ public class NormalProxy extends BaseProxy { // because if not global hooks installed in initZygote might not be // propagated to processes not forked via forkAndSpecialize mRouter.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); } public void forkSystemServerPost(int pid) { @@ -65,7 +61,6 @@ public class NormalProxy extends BaseProxy { ConfigManager.appDataDir = getDataPathPrefix() + "android"; ConfigManager.niceName = "system_server"; mRouter.prepare(true); - Zygote.reopenFilesAfterFork(); mRouter.onEnterChildProcess(); // reload module list if dynamic mode is on mRouter.loadModulesSafely(false); diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 8818ada5..264363c6 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -3,10 +3,10 @@ import org.gradle.internal.os.OperatingSystem apply plugin: 'com.android.library' -version "v0.4.4.1_alpha" +version "v0.4.4.2_alpha" ext { - versionCode = "4410" + versionCode = "4420" module_name = "EdXposed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index 4ff0dd96..4c53f3e9 100644 --- a/edxp-core/src/main/cpp/main/include/config.h +++ b/edxp-core/src/main/cpp/main/include/config.h @@ -21,20 +21,26 @@ namespace edxp { static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:" "/system/framework/eddalvikdx.jar:" "/system/framework/eddexmaker.jar"; + static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook"; static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; + static constexpr auto kLibArtName = "libart.so"; + static constexpr auto kLibFwkName = "libandroid_runtime.so"; + static const auto kLibBasePath = std::string(LP_SELECT("/system/lib/", "/system/lib64/")); - static const auto kLibRuntimeBasePath = std::string(LP_SELECT("/apex/com.android.runtime/lib/", - "/apex/com.android.runtime/lib64/")); + static const auto kLibRuntimeBasePath = std::string( + LP_SELECT("/apex/com.android.runtime/lib/", "/apex/com.android.runtime/lib64/")); + static const auto kLibArtPath = - (GetAndroidApiLevel() >= ANDROID_Q ? kLibRuntimeBasePath : kLibBasePath) + "libart.so"; + (GetAndroidApiLevel() >= ANDROID_Q ? kLibRuntimeBasePath : kLibBasePath) + kLibArtName; static const auto kLibWhalePath = kLibBasePath + "libwhale.edxp.so"; static const auto kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so"; static const auto kLibFwPath = kLibBasePath + "libandroidfw.so"; static const auto kLibDlPath = kLibBasePath + "libdl.so"; + static const auto kLibFwkPath = kLibBasePath + kLibFwkName; inline const char *const BoolToString(bool b) { return b ? "true" : "false"; diff --git a/edxp-core/src/main/cpp/main/include/framework/fd_utils.h b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h new file mode 100644 index 00000000..a576337d --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h @@ -0,0 +1,37 @@ + +#pragma once + +#include +#include "base/object.h" + +namespace android { + + // Static whitelist of open paths that the zygote is allowed to keep open. + static const char *kPathWhitelist[] = { + "/data/app/", + "/data/app-private/" + }; + + class FileDescriptorWhitelist : public edxp::HookedObject { + + public: + FileDescriptorWhitelist(void *thiz) : HookedObject(thiz) {} + + static void Setup(void *handle, HookFunType hook_func) { + HOOK_FUNC(IsAllowed, + "_ZNK23FileDescriptorWhitelist9IsAllowedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"); + } + + private: + + CREATE_HOOK_STUB_ENTRIES(bool, IsAllowed, void *thiz, const std::string &path) { + for (const auto &whitelist_path : kPathWhitelist) { + if (android::base::StartsWith(path, whitelist_path)) + return true; + } + return IsAllowedBackup(thiz, path); + } + + }; + +} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index 2115af77..56a0eede 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -16,19 +16,23 @@ #include "art/runtime/class_linker.h" #include "art/runtime/gc/heap.h" #include "art/runtime/hidden_api.h" +#include "framework/fd_utils.h" namespace edxp { static bool installed = false; static bool art_hooks_installed = false; + static bool fwk_hooks_installed = false; static HookFunType hook_func = nullptr; void InstallArtHooks(void *art_handle); + void InstallFwkHooks(void *fwk_handle); + CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags, const void *caller) { void *handle = mydlopenBackup(file_name, flags, caller); - if (std::string(file_name).find("libart.so") != std::string::npos) { + if (std::string(file_name).find(kLibArtName) != std::string::npos) { InstallArtHooks(handle); } return handle; @@ -69,6 +73,9 @@ namespace edxp { ScopedDlHandle art_handle(kLibArtPath.c_str()); InstallArtHooks(art_handle.Get()); } + + ScopedDlHandle fwk_handle(kLibFwkPath.c_str()); + InstallFwkHooks(fwk_handle.Get()); } void InstallArtHooks(void *art_handle) { @@ -85,5 +92,12 @@ namespace edxp { LOGI("ART hooks installed"); } + void InstallFwkHooks(void *fwk_handle) { + if (fwk_hooks_installed) { + return; + } + android::FileDescriptorWhitelist::Setup(fwk_handle, hook_func); + } + } diff --git a/edxp-core/template_override/common/util_functions.sh b/edxp-core/template_override/common/util_functions.sh index f6795fd5..9aaed487 100644 --- a/edxp-core/template_override/common/util_functions.sh +++ b/edxp-core/template_override/common/util_functions.sh @@ -1,6 +1,6 @@ #!/system/bin/sh -EDXP_VERSION="0.4.4.1_alpha (4410)" +EDXP_VERSION="0.4.4.2_alpha (4420)" ANDROID_SDK=`getprop ro.build.version.sdk` BUILD_DESC=`getprop ro.build.description` PRODUCT=`getprop ro.build.product`