Suspend all threads when doing hook stuffs to prevent crashes caused by GC
This commit is contained in:
parent
9a0044b674
commit
2ac5eb19c9
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,9 +112,14 @@ public class HookMain {
|
|||
if (backup != null) {
|
||||
HookMethodResolver.resolveMethod(hook, backup);
|
||||
}
|
||||
long obj = Main.suspendAllThreads();
|
||||
try {
|
||||
if (!backupAndHookNative(target, hook, backup)) {
|
||||
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
||||
}
|
||||
} finally {
|
||||
Main.resumeAllThreads(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object findMethod(Class cls, String methodName, String methodSig) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue