Fix JNI ref leaks
This commit is contained in:
parent
3d863cb4c2
commit
c4978b7344
|
|
@ -123,6 +123,11 @@ public class Main implements KeepAll {
|
|||
return edxpImplRef.get();
|
||||
}
|
||||
|
||||
@EdxpImpl.Variant
|
||||
public static synchronized int getEdxpVariant() {
|
||||
return getEdxpImpl().getVariant();
|
||||
}
|
||||
|
||||
private static void loadEdxpImpls() {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
|
|
@ -133,7 +138,7 @@ public class Main implements KeepAll {
|
|||
iterator.next();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// Do nothing
|
||||
Utils.logE("error when loadEdxpImpls", t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ import org.gradle.internal.os.OperatingSystem
|
|||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
version "v0.4.4.0_alpha"
|
||||
version "v0.4.4.1_alpha"
|
||||
|
||||
ext {
|
||||
versionCode = "4400"
|
||||
versionCode = "4410"
|
||||
module_name = "EdXposed"
|
||||
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
||||
is_windows = OperatingSystem.current().isWindows()
|
||||
|
|
|
|||
|
|
@ -85,7 +85,11 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) {
|
|||
|
||||
#define JNI_CallStaticObjectMethod(env, obj, ...) \
|
||||
env->CallStaticObjectMethod(obj, __VA_ARGS__); \
|
||||
if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__);
|
||||
if (ClearException(env)) LOGE("CallStaticObjectMethod " #obj " " #__VA_ARGS__);
|
||||
|
||||
#define JNI_CallStaticIntMethod(env, obj, ...) \
|
||||
env->CallStaticIntMethod(obj, __VA_ARGS__); \
|
||||
if (ClearException(env)) LOGE("CallStaticIntMethod " #obj " " #__VA_ARGS__);
|
||||
|
||||
#define JNI_GetArrayLength(env, array) \
|
||||
env->GetArrayLength(array); \
|
||||
|
|
|
|||
|
|
@ -13,16 +13,25 @@ namespace art {
|
|||
return NewLocalRefSym(env, mirror_ptr);
|
||||
}
|
||||
|
||||
CREATE_FUNC_SYMBOL_ENTRY(void, DeleteLocalRef, void *env, jobject obj) {
|
||||
DeleteLocalRefSym(env, obj);
|
||||
}
|
||||
|
||||
public:
|
||||
JNIEnvExt(void *thiz) : HookedObject(thiz) {}
|
||||
|
||||
static void Setup(void *handle, HookFunType hook_func) {
|
||||
RETRIEVE_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE");
|
||||
RETRIEVE_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject");
|
||||
}
|
||||
|
||||
jobject NewLocalRefer(void *mirror_ptr) {
|
||||
return NewLocalRef(thiz_, mirror_ptr);
|
||||
}
|
||||
|
||||
void DeleteLocalRef(jobject obj) {
|
||||
DeleteLocalRef(thiz_, obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,13 +33,14 @@ namespace edxp {
|
|||
}
|
||||
|
||||
void Context::CallOnPostFixupStaticTrampolines(void *class_ptr) {
|
||||
if (post_fixup_static_mid_ != nullptr) {
|
||||
JNIEnv *env;
|
||||
vm_->GetEnv((void **) (&env), JNI_VERSION_1_4);
|
||||
art::JNIEnvExt env_ext(env);
|
||||
jobject clazz = env_ext.NewLocalRefer(class_ptr);
|
||||
JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz);
|
||||
if (UNLIKELY(!post_fixup_static_mid_ || !class_linker_class_)) {
|
||||
return;
|
||||
}
|
||||
JNIEnv *env;
|
||||
vm_->GetEnv((void **) (&env), JNI_VERSION_1_4);
|
||||
art::JNIEnvExt env_ext(env);
|
||||
ScopedLocalRef clazz(env, env_ext.NewLocalRefer(class_ptr));
|
||||
JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz.get());
|
||||
}
|
||||
|
||||
void Context::LoadDexAndInit(JNIEnv *env, const char *dex_path) {
|
||||
|
|
@ -60,12 +61,22 @@ namespace edxp {
|
|||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
||||
jobject my_cl = JNI_NewObject(env, path_classloader, initMid, env->NewStringUTF(dex_path),
|
||||
nullptr, sys_classloader);
|
||||
if (UNLIKELY(!my_cl)) {
|
||||
|
||||
env->DeleteLocalRef(classloader);
|
||||
env->DeleteLocalRef(sys_classloader);
|
||||
env->DeleteLocalRef(path_classloader);
|
||||
|
||||
if (UNLIKELY(my_cl == nullptr)) {
|
||||
LOG(ERROR) << "PathClassLoader creation failed!!!";
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO clear up all these global refs if blacklisted?
|
||||
|
||||
inject_class_loader_ = env->NewGlobalRef(my_cl);
|
||||
|
||||
env->DeleteLocalRef(my_cl);
|
||||
|
||||
// initialize pending methods related
|
||||
env->GetJavaVM(&vm_);
|
||||
class_linker_class_ = (jclass) env->NewGlobalRef(
|
||||
|
|
@ -84,22 +95,36 @@ namespace edxp {
|
|||
RegisterArtHeap(env);
|
||||
RegisterEdxpYahfa(env);
|
||||
|
||||
// must call entry class's methods after all native methods registered
|
||||
if (LIKELY(entry_class_)) {
|
||||
jmethodID get_variant_mid = JNI_GetStaticMethodID(env, entry_class_,
|
||||
"getEdxpVariant", "()I");
|
||||
if (LIKELY(get_variant_mid)) {
|
||||
int variant = JNI_CallStaticIntMethod(env, entry_class_, get_variant_mid);
|
||||
variant_ = static_cast<Variant>(variant);
|
||||
}
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
//for SandHook variant
|
||||
ScopedDlHandle sandhook_handle(kLibSandHookPath.c_str());
|
||||
if (!sandhook_handle.IsValid()) {
|
||||
return;
|
||||
}
|
||||
typedef bool *(*TYPE_JNI_LOAD)(JNIEnv *, jclass, jclass);
|
||||
auto jni_load = sandhook_handle.DlSym<TYPE_JNI_LOAD>("JNI_Load_Ex");
|
||||
jclass sandhook_class = FindClassFromLoader(env, kSandHookClassName);
|
||||
jclass nevercall_class = FindClassFromLoader(env, kSandHookNeverCallClassName);
|
||||
if (!sandhook_class || !nevercall_class) { // fail-fast
|
||||
return;
|
||||
}
|
||||
if (!jni_load(env, sandhook_class, nevercall_class)) {
|
||||
LOGE("SandHook: HookEntry class error. %d", getpid());
|
||||
if (variant_ == SANDHOOK) {
|
||||
//for SandHook variant
|
||||
ScopedDlHandle sandhook_handle(kLibSandHookPath.c_str());
|
||||
if (!sandhook_handle.IsValid()) {
|
||||
return;
|
||||
}
|
||||
typedef bool *(*TYPE_JNI_LOAD)(JNIEnv *, jclass, jclass);
|
||||
auto jni_load = sandhook_handle.DlSym<TYPE_JNI_LOAD>("JNI_Load_Ex");
|
||||
ScopedLocalRef sandhook_class(env, FindClassFromLoader(env, kSandHookClassName));
|
||||
ScopedLocalRef nevercall_class(env,
|
||||
FindClassFromLoader(env, kSandHookNeverCallClassName));
|
||||
if (sandhook_class == nullptr || nevercall_class == nullptr) { // fail-fast
|
||||
return;
|
||||
}
|
||||
if (!jni_load(env, sandhook_class.get(), nevercall_class.get())) {
|
||||
LOGE("SandHook: HookEntry class error. %d", getpid());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +161,7 @@ namespace edxp {
|
|||
|
||||
inline void Context::FindAndCall(JNIEnv *env, const char *method_name,
|
||||
const char *method_sig, ...) const {
|
||||
if (!entry_class_) {
|
||||
if (UNLIKELY(!entry_class_)) {
|
||||
LOGE("cannot call method %s, entry class is null", method_name);
|
||||
return;
|
||||
}
|
||||
|
|
@ -235,8 +260,7 @@ namespace edxp {
|
|||
if (res == 0) {
|
||||
PrepareJavaEnv(env);
|
||||
FindAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;Ljava/lang/String;)V",
|
||||
res,
|
||||
app_data_dir_, nice_name_);
|
||||
res, app_data_dir_, nice_name_);
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ namespace edxp {
|
|||
|
||||
#define SYSTEM_SERVER_DATA_DIR "/data/user/0/android"
|
||||
|
||||
enum Variant {
|
||||
NONE = 0,
|
||||
YAHFA = 1,
|
||||
SANDHOOK = 2,
|
||||
WHALE = 3
|
||||
};
|
||||
|
||||
class Context {
|
||||
|
||||
public:
|
||||
|
|
@ -52,6 +59,7 @@ namespace edxp {
|
|||
private:
|
||||
static Context *instance_;
|
||||
bool initialized_ = false;
|
||||
Variant variant_ = NONE;
|
||||
jobject inject_class_loader_ = nullptr;
|
||||
jclass entry_class_ = nullptr;
|
||||
jstring app_data_dir_ = nullptr;
|
||||
|
|
|
|||
|
|
@ -62,13 +62,12 @@ namespace edxp {
|
|||
hook_func = reinterpret_cast<HookFunType>(hook_func_symbol);
|
||||
|
||||
if (api_level >= ANDROID_P) {
|
||||
void *handle = DlOpen(kLibDlPath.c_str());
|
||||
ScopedDlHandle dl_handle(kLibDlPath.c_str());
|
||||
void *handle = dl_handle.Get();
|
||||
HOOK_FUNC(mydlopen, "__loader_dlopen");
|
||||
dlclose(handle);
|
||||
} else {
|
||||
void *art_handle = DlOpen(kLibArtPath.c_str());
|
||||
InstallArtHooks(art_handle);
|
||||
dlclose(art_handle);
|
||||
ScopedDlHandle art_handle(kLibArtPath.c_str());
|
||||
InstallArtHooks(art_handle.Get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/system/bin/sh
|
||||
|
||||
EDXP_VERSION="0.4.4.0_alpha (4400)"
|
||||
EDXP_VERSION="0.4.4.1_alpha (4410)"
|
||||
ANDROID_SDK=`getprop ro.build.version.sdk`
|
||||
BUILD_DESC=`getprop ro.build.description`
|
||||
PRODUCT=`getprop ro.build.product`
|
||||
|
|
|
|||
Loading…
Reference in New Issue