From 6254660b9b4869524f5b5fbe36cf0cdbb073b4b5 Mon Sep 17 00:00:00 2001 From: solohsu Date: Wed, 20 Feb 2019 03:05:40 +0800 Subject: [PATCH] Prevent OnePlus Android P from bootloop --- .../com/elderdrivers/riru/xposed/Main.java | 3 +- .../riru/xposed/core/HookMain.java | 9 +++- .../riru/xposed/entry/Router.java | 6 +++ .../entry/bootstrap/AppBootstrapHookInfo.java | 4 +- .../entry/bootstrap/SysBootstrapHookInfo.java | 4 +- .../entry/hooker/OnePlusWorkAroundHooker.java | 42 +++++++++++++++++++ 6 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/OnePlusWorkAroundHooker.java 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 81384bdb..37d41b22 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -43,7 +43,6 @@ public class Main implements KeepAll { // entry points /////////////////////////////////////////////////////////////////////////////////////////////// - @Deprecated public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, @@ -74,6 +73,7 @@ public class Main implements KeepAll { public static void forkAndSpecializePost(int pid, String appDataDir) { if (pid == 0) { Utils.logD(sForkAndSpecializePramsStr + " = " + Process.myPid()); + Router.onEnterChildProcess(); DynamicBridge.onForkPost(); // in app process if (!sIsGlobalMode) { @@ -106,6 +106,7 @@ public class Main implements KeepAll { if (pid == 0) { Utils.logD(sForkSystemServerPramsStr + " = " + Process.myPid()); // in system_server process + Router.onEnterChildProcess(); Router.prepare(true); Router.onProcessForked(true); Router.loadModulesSafely(); diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java index f8418450..21ad22f1 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/core/HookMain.java @@ -1,5 +1,6 @@ package com.elderdrivers.riru.xposed.core; +import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker; import com.elderdrivers.riru.xposed.util.Utils; import java.lang.reflect.Constructor; @@ -7,12 +8,16 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Set; import static com.elderdrivers.riru.xposed.Main.backupAndHookNative; import static com.elderdrivers.riru.xposed.Main.findMethodNative; public class HookMain { + private static Set hookItemWhiteList = Collections.singleton(OnePlusWorkAroundHooker.class.getName()); + public static void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader, String hookInfoClassName) { try { Class hookInfoClass = Class.forName(hookInfoClassName, true, patchClassLoader); @@ -64,7 +69,9 @@ public class HookMain { } findAndBackupAndHook(clazz, methodName, methodSig, hook, backup); } catch (Throwable e) { - Utils.logE("error when hooking " + hookItemName, e); + if (!hookItemWhiteList.contains(hookItemName)) { + Utils.logE("error when hooking " + hookItemName, e); + } } } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java index 829eb4c0..1230f12f 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java @@ -71,4 +71,10 @@ public class Router { SystemMainHooker.systemServerCL, SysInnerHookInfo.class.getName()); } + + public volatile static boolean forkCompleted = false; + + public static void onEnterChildProcess() { + forkCompleted = true; + } } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/AppBootstrapHookInfo.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/AppBootstrapHookInfo.java index 0fc91240..714ea2fc 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/AppBootstrapHookInfo.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/AppBootstrapHookInfo.java @@ -3,10 +3,12 @@ package com.elderdrivers.riru.xposed.entry.bootstrap; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.xposed.entry.hooker.HandleBindAppHooker; import com.elderdrivers.riru.xposed.entry.hooker.LoadedApkConstructorHooker; +import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { HandleBindAppHooker.class.getName(), - LoadedApkConstructorHooker.class.getName() + LoadedApkConstructorHooker.class.getName(), + OnePlusWorkAroundHooker.class.getName() }; } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/SysBootstrapHookInfo.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/SysBootstrapHookInfo.java index 86d03955..cca1e6b8 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/SysBootstrapHookInfo.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/bootstrap/SysBootstrapHookInfo.java @@ -3,12 +3,14 @@ package com.elderdrivers.riru.xposed.entry.bootstrap; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.xposed.entry.hooker.HandleBindAppHooker; import com.elderdrivers.riru.xposed.entry.hooker.LoadedApkConstructorHooker; +import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker; import com.elderdrivers.riru.xposed.entry.hooker.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { HandleBindAppHooker.class.getName(), SystemMainHooker.class.getName(), - LoadedApkConstructorHooker.class.getName() + LoadedApkConstructorHooker.class.getName(), + OnePlusWorkAroundHooker.class.getName() }; } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/OnePlusWorkAroundHooker.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/OnePlusWorkAroundHooker.java new file mode 100644 index 00000000..f545da8e --- /dev/null +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/OnePlusWorkAroundHooker.java @@ -0,0 +1,42 @@ +package com.elderdrivers.riru.xposed.entry.hooker; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.xposed.entry.Router; + +import de.robv.android.xposed.XposedBridge; + +import static de.robv.android.xposed.XposedInit.logD; + +/** + * On OnePlus stock roms (Android Pie), {@link dalvik.system.BaseDexClassLoader#findClass(String)} + * will open /dev/binder to communicate with PackageManagerService to check whether + * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when + * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: + * https://gist.github.com/solohsu/ecc07141759958fc096ba0781fac0a5f) + * If we invoke intZygoteCallbacks in + * {@link com.elderdrivers.riru.xposed.Main#forkAndSpecializePre}, where in zygote process, + * we would get a chance to invoke findclass, leaving fd of /dev/binder open in zygote process, + * which is not allowed because /dev/binder is not in predefined whitelist here: + * http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/fd_utils.cpp#35 + * So we just hook BaseDexClassLoader#inCompatConfigList to return false to prevent + * open of /dev/binder and we haven't found side effects yet. + * Other roms might share the same problems but not reported too. + */ +public class OnePlusWorkAroundHooker implements KeepMembers { + + public static String className = "dalvik.system.BaseDexClassLoader"; + public static String methodName = "inCompatConfigList"; + public static String methodSig = "(ILjava/lang/String;)Z"; + + public static boolean hook(int type, String packageName) { + if (XposedBridge.disableHooks || Router.forkCompleted) { + return backup(type, packageName); + } + logD("BaseDexClassLoader#inCompatConfigList() starts"); + return false; + } + + public static boolean backup(int type, String packageName) { + return false; + } +} \ No newline at end of file