Skip to content

Commit

Permalink
Suspend all threads when doing hook stuffs to prevent crashes caused …
Browse files Browse the repository at this point in the history
…by GC
  • Loading branch information
solohsu committed Feb 28, 2019
1 parent 9a0044b commit 2ac5eb1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 10 deletions.
4 changes: 4 additions & 0 deletions Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,8 @@ public static void forkSystemServerPost(int pid, boolean isBlackWhiteListMode,
public static native void reopenFilesAfterForkNative();

public static native void deoptMethodNative(Object object);

public static native long suspendAllThreads();

public static native void resumeAllThreads(long obj);
}
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -111,8 +112,13 @@ public static void backupAndHook(Object target, Method hook, Method backup) {
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();

This comment has been minimized.

Copy link
@C3C0

C3C0 Mar 5, 2019

Contributor

This seems to have made situation worse. See #127
I am getting far less GC related crashes without it.

This comment has been minimized.

Copy link
@solohsu

solohsu Mar 5, 2019

Author Member

Well, maybe this is not the right way to go. I can confirm it's buggy. A better solution needs to be found.

try {
if (!backupAndHookNative(target, hook, backup)) {
throw new RuntimeException("Failed to hook " + target + " with " + hook);
}
} finally {
Main.resumeAllThreads(obj);
}
}

Expand Down
38 changes: 30 additions & 8 deletions Core/jni/main/java_hook/java_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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",
Expand All @@ -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
},
{
"reopenFilesAfterForkNative", "()V", (void *) reopenFilesAfterForkNative
},
{
"closeFilesBeforeForkNative", "()V", (void *)closeFilesBeforeForkNative
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *) deoptimize_method
},
{
"reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative
"suspendAllThreads", "()J", (void *) suspendAllThreads
},
{
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *)deoptimize_method
"resumeAllThreads", "(J)V", (void *) resumeAllThreads
}
};

Expand Down Expand Up @@ -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 {
Expand Down
14 changes: 14 additions & 0 deletions Core/jni/main/native_hook/native_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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.");
Expand Down
7 changes: 7 additions & 0 deletions Core/jni/main/native_hook/native_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 2ac5eb1

Please sign in to comment.