From c94f5543c04e5469de27a055b3bce2d36f0ea9ea Mon Sep 17 00:00:00 2001 From: Shauli Bracha Date: Mon, 25 Feb 2019 15:54:00 +0200 Subject: [PATCH 1/3] supolicy: added system_app to mlstrustedsubject (#109) * supolicy: added system_app to mlstrustedsubject * Update post-fs-data.sh --- Core/template_override/common/post-fs-data.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/template_override/common/post-fs-data.sh b/Core/template_override/common/post-fs-data.sh index 271effea..0dd4bef7 100644 --- a/Core/template_override/common/post-fs-data.sh +++ b/Core/template_override/common/post-fs-data.sh @@ -18,7 +18,7 @@ supolicy --live "allow coredomain coredomain process {execmem}" # read configs set in our app supolicy --live "allow {zygote system_server} app_data_file * *" -supolicy --live "attradd platform_app mlstrustedsubject" +supolicy --live "attradd {system_app platform_app} mlstrustedsubject" # read module apk file in zygote supolicy --live "allow zygote apk_data_file * *" From 628d4e7ab0f0d09c425d94bf165f7d68d9063953 Mon Sep 17 00:00:00 2001 From: solohsu Date: Wed, 27 Feb 2019 01:38:40 +0800 Subject: [PATCH 2/3] Add an interface to deoptimize specified ArtMethod for Android Pie --- .../com/elderdrivers/riru/xposed/Main.java | 2 + Core/jni/main/inject/config_manager.cpp | 2 +- Core/jni/main/inject/config_manager.h | 2 +- Core/jni/main/java_hook/java_hook.cpp | 6 +- Core/jni/main/native_hook/native_hook.cpp | 75 +++++++++++++++++-- Core/jni/main/native_hook/native_hook.h | 2 + 6 files changed, 79 insertions(+), 10 deletions(-) diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java index e288b725..e8eeda96 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -123,4 +123,6 @@ public class Main implements KeepAll { public static native void closeFilesBeforeForkNative(); public static native void reopenFilesAfterForkNative(); + + public static native void deoptMethodNative(Object object); } diff --git a/Core/jni/main/inject/config_manager.cpp b/Core/jni/main/inject/config_manager.cpp index 0780718a..b8447eeb 100644 --- a/Core/jni/main/inject/config_manager.cpp +++ b/Core/jni/main/inject/config_manager.cpp @@ -136,7 +136,7 @@ bool is_dynamic_modules_enabled() { return dynamic_modules_enabled; } -jstring get_installer_pkg_name(JNIEnv *env) { +jstring get_installer_pkg_name(JNIEnv *env, jclass clazz) { init_once(); return env->NewStringUTF(installer_package_name); } diff --git a/Core/jni/main/inject/config_manager.h b/Core/jni/main/inject/config_manager.h index f9561f66..8bd831c7 100644 --- a/Core/jni/main/inject/config_manager.h +++ b/Core/jni/main/inject/config_manager.h @@ -11,6 +11,6 @@ bool is_black_white_list_enabled(); bool is_dynamic_modules_enabled(); -jstring get_installer_pkg_name(JNIEnv *env); +jstring get_installer_pkg_name(JNIEnv *env, jclass clazz); #endif //EDXPOSED_CONFIG_MANAGER_H diff --git a/Core/jni/main/java_hook/java_hook.cpp b/Core/jni/main/java_hook/java_hook.cpp index f11f35ba..2baf2a03 100644 --- a/Core/jni/main/java_hook/java_hook.cpp +++ b/Core/jni/main/java_hook/java_hook.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "java_hook/java_hook.h" #include "include/logging.h" #include "include/fd_utils-inl.h" @@ -64,6 +65,9 @@ static JNINativeMethod hookMethods[] = { }, { "reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative + }, + { + "deoptMethodNative", "(Ljava/lang/Object;)V", (void *)deoptimize_method } }; @@ -102,7 +106,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) { jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME); if (NULL != entry_class) { LOGD("HookEntry Class %p", entry_class); - env->RegisterNatives(entry_class, hookMethods, 7); + env->RegisterNatives(entry_class, hookMethods, 8); isInited = true; LOGD("RegisterNatives succeed for HookEntry."); } else { diff --git a/Core/jni/main/native_hook/native_hook.cpp b/Core/jni/main/native_hook/native_hook.cpp index 71cb767d..5a2b9808 100644 --- a/Core/jni/main/native_hook/native_hook.cpp +++ b/Core/jni/main/native_hook/native_hook.cpp @@ -13,12 +13,20 @@ static const char *(*getDesc)(void *, std::string *); static bool (*isInSamePackageBackup)(void *, void *) = nullptr; +// runtime void *runtime_ = nullptr; void (*deoptBootImage)(void *runtime) = nullptr; bool (*runtimeInitBackup)(void *runtime, void *mapAddr) = nullptr; +// instrumentation +void *instru_ = nullptr; + +static void *(*instrCstBackup)(void *instru) = nullptr; + +void (*deoptMethod)(void *, void *) = nullptr; + bool my_runtimeInit(void *runtime, void *mapAddr) { if (!runtimeInitBackup) { LOGE("runtimeInitBackup is null"); @@ -45,7 +53,6 @@ static bool onIsInSamePackageCalled(void *thiz, void *that) { || strstr(thatDesc, "EdHooker") != nullptr || strstr(thisDesc, "com/elderdrivers/riru/") != nullptr || strstr(thatDesc, "com/elderdrivers/riru/") != nullptr) { -// LOGE("onIsInSamePackageCalled, %s -> %s", thisDesc, thatDesc); return true; } return (*isInSamePackageBackup)(thiz, that); @@ -61,8 +68,8 @@ static bool onInvokeHiddenAPI() { * But we don't know the symbols until it's published. * @author asLody */ -static bool disable_HiddenAPIPolicyImpl(int api_level, void *artHandle, - void (*hookFun)(void *, void *, void **)) { +static bool disableHiddenAPIPolicyImpl(int api_level, void *artHandle, + void (*hookFun)(void *, void *, void **)) { if (api_level < ANDROID_P) { return true; } @@ -121,6 +128,59 @@ static void hookIsInSamePackage(int api_level, void *artHandle, reinterpret_cast(&isInSamePackageBackup)); } +void *my_instruCst(void *instru) { + if (!instrCstBackup) { + LOGE("instrCstBackup is null"); + return instru; + } + LOGI("instrCst starts"); + void *result = (*instrCstBackup)(instru); + LOGI("instrCst finishes"); + if (instru_ != instru) { + LOGI("instru_ changed from %p to %p", instru_, instru); + instru_ = instru; + } + return result; +} + +void hookInstrumentation(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) { + if (api_level < ANDROID_P) { + // TODO support other api levels + return; + } + void *instruCstSym = dlsym(artHandle, + "_ZN3art15instrumentation15InstrumentationC2Ev"); + deoptMethod = reinterpret_cast( + dlsym(artHandle, + "_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE")); + if (!instruCstSym) { + LOGE("can't get instruCstSym: %s", dlerror()); + return; + } + (*hookFun)(instruCstSym, reinterpret_cast(my_instruCst), + reinterpret_cast(&instrCstBackup)); + LOGI("instrCst hooked"); +} + +std::vector deoptedMethods; + +void deoptimize_method(JNIEnv *env, jclass clazz, jobject method) { + if (!deoptMethod) { + LOGE("deoptMethodSym is null, skip deopt"); + return; + } + void *reflected_method = env->FromReflectedMethod(method); + if (std::find(deoptedMethods.begin(), deoptedMethods.end(), reflected_method) != + deoptedMethods.end()) { + LOGD("method %p has been deopted before, skip...", reflected_method); + return; + } + LOGD("deoptimize method: %p", reflected_method); + (*deoptMethod)(instru_, reflected_method); + deoptedMethods.push_back(reflected_method); + LOGD("deoptimize method done: %p"); +} + void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) { void *runtimeInitSym = nullptr; if (api_level >= ANDROID_O) { @@ -177,12 +237,13 @@ void install_inline_hooks() { LOGE("can't open libart: %s", dlerror()); return; } - hookIsInSamePackage(api_level, artHandle, hookFun); hookRuntime(api_level, artHandle, hookFun); - if (disable_HiddenAPIPolicyImpl(api_level, artHandle, hookFun)) { - LOGI("disable_HiddenAPIPolicyImpl done."); + hookInstrumentation(api_level, artHandle, hookFun); + hookIsInSamePackage(api_level, artHandle, hookFun); + if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) { + LOGI("disableHiddenAPIPolicyImpl done."); } else { - LOGE("disable_HiddenAPIPolicyImpl failed."); + LOGE("disableHiddenAPIPolicyImpl failed."); } dlclose(whaleHandle); dlclose(artHandle); diff --git a/Core/jni/main/native_hook/native_hook.h b/Core/jni/main/native_hook/native_hook.h index fab2f98b..e9843289 100644 --- a/Core/jni/main/native_hook/native_hook.h +++ b/Core/jni/main/native_hook/native_hook.h @@ -21,4 +21,6 @@ static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so"; void install_inline_hooks(); +void deoptimize_method(JNIEnv *env, jclass clazz, jobject method); + #endif // HOOK_H From 9a0044b67405541b4e49ac44e5f0eb08c7076e3b Mon Sep 17 00:00:00 2001 From: solohsu Date: Thu, 28 Feb 2019 00:51:06 +0800 Subject: [PATCH 3/3] Add a switch to enable boot image deoptimization selectively --- Core/jni/main/inject/config_manager.cpp | 12 +++++++++++- Core/jni/main/inject/config_manager.h | 4 ++++ Core/jni/main/native_hook/native_hook.cpp | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Core/jni/main/inject/config_manager.cpp b/Core/jni/main/inject/config_manager.cpp index b8447eeb..5af64060 100644 --- a/Core/jni/main/inject/config_manager.cpp +++ b/Core/jni/main/inject/config_manager.cpp @@ -27,10 +27,12 @@ static char whitelist_path[PATH_MAX]; static char use_whitelist_path[PATH_MAX]; static char black_white_list_path[PATH_MAX]; static char dynamic_modules_path[PATH_MAX]; +static char deopt_boot_image_path[PATH_MAX]; static const char *installer_package_name; static bool black_white_list_enabled = false; static bool dynamic_modules_enabled = false; +static bool deopt_boot_image_enabled = false; static bool inited = false; static const char *get_installer_package_name() { @@ -72,8 +74,11 @@ static void init_once() { installer_package_name, "blackwhitelist"); snprintf(dynamic_modules_path, PATH_MAX, config_path_tpl, data_path_prefix, installer_package_name, "dynamicmodules"); + snprintf(deopt_boot_image_path, PATH_MAX, config_path_tpl, data_path_prefix, + installer_package_name, "deoptbootimage"); dynamic_modules_enabled = access(dynamic_modules_path, F_OK) == 0; black_white_list_enabled = access(black_white_list_path, F_OK) == 0; + deopt_boot_image_enabled = access(deopt_boot_image_path, F_OK) == 0; LOGI("black/white list mode: %d", black_white_list_enabled); LOGI("dynamic modules mode: %d", dynamic_modules_enabled); inited = true; @@ -136,7 +141,12 @@ bool is_dynamic_modules_enabled() { return dynamic_modules_enabled; } -jstring get_installer_pkg_name(JNIEnv *env, jclass clazz) { +bool is_deopt_boot_image_enabled() { + init_once(); + return deopt_boot_image_enabled; +} + +jstring get_installer_pkg_name(JNIEnv *env, jclass) { init_once(); return env->NewStringUTF(installer_package_name); } diff --git a/Core/jni/main/inject/config_manager.h b/Core/jni/main/inject/config_manager.h index 8bd831c7..8fb59259 100644 --- a/Core/jni/main/inject/config_manager.h +++ b/Core/jni/main/inject/config_manager.h @@ -5,12 +5,16 @@ #ifndef EDXPOSED_CONFIG_MANAGER_H #define EDXPOSED_CONFIG_MANAGER_H +#include + bool is_app_need_hook(JNIEnv *env, jstring appDataDir); bool is_black_white_list_enabled(); bool is_dynamic_modules_enabled(); +bool is_deopt_boot_image_enabled(); + jstring get_installer_pkg_name(JNIEnv *env, jclass clazz); #endif //EDXPOSED_CONFIG_MANAGER_H diff --git a/Core/jni/main/native_hook/native_hook.cpp b/Core/jni/main/native_hook/native_hook.cpp index 5a2b9808..3bb3fb11 100644 --- a/Core/jni/main/native_hook/native_hook.cpp +++ b/Core/jni/main/native_hook/native_hook.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "include/logging.h" #include "native_hook.h" @@ -182,6 +183,9 @@ void deoptimize_method(JNIEnv *env, jclass clazz, jobject method) { } void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) { + if (!is_deopt_boot_image_enabled()) { + return; + } void *runtimeInitSym = nullptr; if (api_level >= ANDROID_O) { // only oreo has deoptBootImageSym in Runtime