Suspend all threads when doing hook stuffs to prevent crashes caused by GC

This commit is contained in:
solohsu 2019-02-28 18:05:01 +08:00
parent 9a0044b674
commit 2ac5eb19c9
5 changed files with 63 additions and 10 deletions

View File

@ -125,4 +125,8 @@ public class Main implements KeepAll {
public static native void reopenFilesAfterForkNative();
public static native void deoptMethodNative(Object object);
public static native long suspendAllThreads();
public static native void resumeAllThreads(long obj);
}

View File

@ -1,5 +1,6 @@
package com.elderdrivers.riru.xposed.core;
import com.elderdrivers.riru.xposed.Main;
import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker;
import com.elderdrivers.riru.xposed.util.Utils;
@ -111,8 +112,13 @@ public class HookMain {
if (backup != null) {
HookMethodResolver.resolveMethod(hook, backup);
}
if (!backupAndHookNative(target, hook, backup)) {
throw new RuntimeException("Failed to hook " + target + " with " + hook);
long obj = Main.suspendAllThreads();
try {
if (!backupAndHookNative(target, hook, backup)) {
throw new RuntimeException("Failed to hook " + target + " with " + hook);
}
} finally {
Main.resumeAllThreads(obj);
}
}

View File

@ -20,13 +20,13 @@ jobject gInjectDexClassLoader;
static bool isInited = false;
static FileDescriptorTable* gClosedFdTable = nullptr;
static FileDescriptorTable *gClosedFdTable = nullptr;
void closeFilesBeforeForkNative(JNIEnv*, jclass) {
void closeFilesBeforeForkNative(JNIEnv *, jclass) {
gClosedFdTable = FileDescriptorTable::Create();
}
void reopenFilesAfterForkNative(JNIEnv*, jclass) {
void reopenFilesAfterForkNative(JNIEnv *, jclass) {
if (!gClosedFdTable) {
LOGE("gClosedFdTable is null when reopening files");
return;
@ -36,6 +36,22 @@ void reopenFilesAfterForkNative(JNIEnv*, jclass) {
gClosedFdTable = nullptr;
}
jlong suspendAllThreads(JNIEnv *, jclass) {
if (!suspendAll) {
return 0;
}
ScopedSuspendAll *suspendAllObj = (ScopedSuspendAll *) malloc(sizeof(ScopedSuspendAll));
suspendAll(suspendAllObj, "edxp_stop_gc", false);
return reinterpret_cast<jlong>(suspendAllObj);
}
void resumeAllThreads(JNIEnv *, jclass, jlong obj) {
if (!resumeAll) {
return;
}
resumeAll(reinterpret_cast<ScopedSuspendAll *>(obj));
}
static JNINativeMethod hookMethods[] = {
{
"init",
@ -58,16 +74,22 @@ static JNINativeMethod hookMethods[] = {
(void *) Java_lab_galaxy_yahfa_HookMain_ensureMethodCached
},
{
"getInstallerPkgName", "()Ljava/lang/String;", (void *)get_installer_pkg_name
"getInstallerPkgName", "()Ljava/lang/String;", (void *) get_installer_pkg_name
},
{
"closeFilesBeforeForkNative", "()V", (void *)closeFilesBeforeForkNative
"closeFilesBeforeForkNative", "()V", (void *) closeFilesBeforeForkNative
},
{
"reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative
"reopenFilesAfterForkNative", "()V", (void *) reopenFilesAfterForkNative
},
{
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *)deoptimize_method
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *) deoptimize_method
},
{
"suspendAllThreads", "()J", (void *) suspendAllThreads
},
{
"resumeAllThreads", "(J)V", (void *) resumeAllThreads
}
};
@ -106,7 +128,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, 8);
env->RegisterNatives(entry_class, hookMethods, 10);
isInited = true;
LOGD("RegisterNatives succeed for HookEntry.");
} else {

View File

@ -212,6 +212,19 @@ void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *,
}
}
void (*suspendAll)(ScopedSuspendAll*, const char*, bool) = nullptr;
void (*resumeAll)(ScopedSuspendAll*) = nullptr;
void getSuspendSyms(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
if (api_level < ANDROID_N) {
return;
}
suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll*,const char*, bool)>(dlsym(artHandle,
"_ZN3art16ScopedSuspendAllC2EPKcb"));
resumeAll = reinterpret_cast<void (*)(ScopedSuspendAll*)>(dlsym(artHandle,
"_ZN3art16ScopedSuspendAllD2Ev"));
}
void install_inline_hooks() {
if (inlineHooksInstalled) {
LOGI("inline hooks installed, skip");
@ -243,6 +256,7 @@ void install_inline_hooks() {
}
hookRuntime(api_level, artHandle, hookFun);
hookInstrumentation(api_level, artHandle, hookFun);
getSuspendSyms(api_level, artHandle, hookFun);
hookIsInSamePackage(api_level, artHandle, hookFun);
if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
LOGI("disableHiddenAPIPolicyImpl done.");

View File

@ -19,6 +19,13 @@ static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so";
static ret (*old_##func)(__VA_ARGS__); \
static ret new_##func(__VA_ARGS__)
class ScopedSuspendAll {
};
extern void (*suspendAll)(ScopedSuspendAll *, const char *, bool);
extern void (*resumeAll)(ScopedSuspendAll *);
void install_inline_hooks();
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method);