Prevent OnePlus Android P from bootloop

This commit is contained in:
solohsu 2019-02-20 03:05:40 +08:00
parent 8b0a9fc11e
commit 6254660b9b
6 changed files with 64 additions and 4 deletions

View File

@ -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();

View File

@ -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<String> 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);
}
}
}

View File

@ -71,4 +71,10 @@ public class Router {
SystemMainHooker.systemServerCL,
SysInnerHookInfo.class.getName());
}
public volatile static boolean forkCompleted = false;
public static void onEnterChildProcess() {
forkCompleted = true;
}
}

View File

@ -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()
};
}

View File

@ -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()
};
}

View File

@ -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;
}
}