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 650599b2..7699c8a2 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -5,6 +5,7 @@ import android.os.Build; import android.os.Process; import com.elderdrivers.riru.common.KeepAll; +import com.elderdrivers.riru.xposed.config.ConfigManager; import com.elderdrivers.riru.xposed.core.HookMethodResolver; import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge; import com.elderdrivers.riru.xposed.entry.Router; @@ -20,13 +21,6 @@ public class Main implements KeepAll { public static String appDataDir = ""; public static String appProcessName = ""; - /** - * When set to true, install bootstrap hooks and loadModules - * for each process when it starts. - * This means you can deactivate or activate every module - * for the process you restart without rebooting. - */ - public static boolean isDynamicModules = false; private static String forkAndSpecializePramsStr = ""; private static String forkSystemServerPramsStr = ""; @@ -43,7 +37,7 @@ public class Main implements KeepAll { int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, - String appDataDir, boolean isDynamicModules) { + String appDataDir) { if (BuildConfig.DEBUG) { forkAndSpecializePramsStr = String.format( "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", @@ -52,7 +46,6 @@ public class Main implements KeepAll { Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); } Main.appDataDir = appDataDir; - Main.isDynamicModules = isDynamicModules; Router.prepare(false); // install bootstrap hooks for secondary zygote Router.installBootstrapHooks(false); @@ -63,9 +56,10 @@ public class Main implements KeepAll { public static void forkAndSpecializePost(int pid, String appDataDir) { if (pid == 0) { Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); + // TODO consider processes without forkAndSpecializePost called Router.onEnterChildProcess(); DynamicBridge.onForkPost(); - if (isDynamicModules) { + if (ConfigManager.isDynamicModulesMode()) { // load modules for each app process on its forked Router.loadModulesSafely(); } @@ -76,15 +70,13 @@ public class Main implements KeepAll { } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - long permittedCapabilities, long effectiveCapabilities, - boolean isDynamicModules) { + long permittedCapabilities, long effectiveCapabilities) { if (BuildConfig.DEBUG) { forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), permittedCapabilities, effectiveCapabilities); } Main.appDataDir = getDataPathPrefix() + "android"; - Main.isDynamicModules = isDynamicModules; Router.prepare(true); // install bootstrap hooks for main zygote as early as possible // in case we miss some processes not forked via forkAndSpecialize diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/config/ConfigManager.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/config/ConfigManager.java new file mode 100644 index 00000000..47701777 --- /dev/null +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/config/ConfigManager.java @@ -0,0 +1,51 @@ +package com.elderdrivers.riru.xposed.config; + +import java.util.Collections; +import java.util.Set; + +import de.robv.android.xposed.SELinuxHelper; +import de.robv.android.xposed.XposedInit; + +import static de.robv.android.xposed.XposedInit.INSTALLER_PACKAGE_NAME; + +public class ConfigManager { + + private static final String BLACK_LIST_PATH = XposedInit.INSTALLER_DATA_BASE_DIR + "conf/blacklist/"; + private static final String WHITE_LIST_PATH = XposedInit.INSTALLER_DATA_BASE_DIR + "conf/whitelist/"; + private static final String COMPAT_LIST_PATH = XposedInit.INSTALLER_DATA_BASE_DIR + "conf/compatlist/"; + private static final String USE_WHITE_LIST = XposedInit.INSTALLER_DATA_BASE_DIR + "conf/usewhitelist"; + private static final String DYNAMIC_MODULES = XposedInit.INSTALLER_DATA_BASE_DIR + "conf/dynamicmodules"; + private static final Set WHITE_LIST = Collections.singleton(INSTALLER_PACKAGE_NAME); + private static final boolean IS_DYNAMIC_MODULES; + + static { + IS_DYNAMIC_MODULES = isFileExists(DYNAMIC_MODULES); + } + + public static boolean isDynamicModulesMode() { + return IS_DYNAMIC_MODULES; + } + + public static boolean shouldUseWhitelist() { + return isFileExists(USE_WHITE_LIST); + } + + public static boolean shouldUseCompatMode(String packageName) { + return isFileExists(COMPAT_LIST_PATH + packageName); + } + + public static boolean shouldHook(String packageName) { + if (WHITE_LIST.contains(packageName)) { + return true; + } + if (shouldUseWhitelist()) { + return isFileExists(WHITE_LIST_PATH + packageName); + } else { + return !isFileExists(BLACK_LIST_PATH + packageName); + } + } + + private static boolean isFileExists(String path) { + return SELinuxHelper.getAppDataFileService().checkFileExists(path); + } +} diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java index 8a5dd8bc..671561f0 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java @@ -5,6 +5,7 @@ import android.os.Build; import android.text.TextUtils; import com.elderdrivers.riru.xposed.Main; +import com.elderdrivers.riru.xposed.config.ConfigManager; import java.util.HashMap; import java.util.Map; @@ -17,7 +18,6 @@ import external.com.android.dx.TypeId; public class DexMakerUtils { private static final boolean IN_MEMORY_DEX_ELIGIBLE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; - private static final String COMPAT_LIST_PATH = "/data/misc/riru/modules/edxposed/compatlist/"; public static boolean shouldUseInMemoryHook() { if (!IN_MEMORY_DEX_ELIGIBLE) { @@ -29,7 +29,7 @@ public class DexMakerUtils { + ", appDataDir=" + Main.appDataDir); return true; } - return !SELinuxHelper.getAppDataFileService().checkFileExists(COMPAT_LIST_PATH + packageName); + return !ConfigManager.shouldUseCompatMode(packageName); } public static void autoBoxIfNecessary(Code code, Local target, Local source) { 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 dcf0c134..2b1e1a26 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 @@ -1,5 +1,9 @@ package com.elderdrivers.riru.xposed.entry; +import android.text.TextUtils; + +import com.elderdrivers.riru.xposed.Main; +import com.elderdrivers.riru.xposed.config.ConfigManager; import com.elderdrivers.riru.xposed.core.HookMain; import com.elderdrivers.riru.xposed.entry.bootstrap.AppBootstrapHookInfo; import com.elderdrivers.riru.xposed.entry.bootstrap.SysBootstrapHookInfo; @@ -19,6 +23,22 @@ public class Router { XposedInit.startsSystemServer = isSystem; } + public static void checkHookState(String appDataDir) { + // determine whether allow xposed or not +// XposedBridge.disableHooks = ConfigManager.shouldHook(parsePackageName(appDataDir)); + } + + private static String parsePackageName(String appDataDir) { + if (TextUtils.isEmpty(appDataDir)) { + return ""; + } + int lastIndex = appDataDir.lastIndexOf("/"); + if (lastIndex < 1) { + return ""; + } + return appDataDir.substring(lastIndex + 1); + } + public static void installBootstrapHooks(boolean isSystem) { // Initialize the Xposed framework try { diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java index 6d4720da..6f3b5200 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -8,7 +8,7 @@ import android.util.Log; import com.android.internal.os.ZygoteInit; import com.elderdrivers.riru.xposed.BuildConfig; -import com.elderdrivers.riru.xposed.Main; +import com.elderdrivers.riru.xposed.config.ConfigManager; import com.elderdrivers.riru.xposed.entry.Router; import com.elderdrivers.riru.xposed.util.Utils; @@ -94,7 +94,8 @@ public final class XposedInit { private static volatile AtomicBoolean modulesLoaded = new AtomicBoolean(false); public static void loadModules() throws IOException { - if (!modulesLoaded.compareAndSet(false, true) && !Main.isDynamicModules) { + if (!modulesLoaded.compareAndSet(false, true) + && !ConfigManager.isDynamicModulesMode()) { return; } XposedBridge.clearLoadedPackages(); diff --git a/Core/jni/main/Android.mk b/Core/jni/main/Android.mk index 0abc2c81..b8bff4fe 100644 --- a/Core/jni/main/Android.mk +++ b/Core/jni/main/Android.mk @@ -18,7 +18,6 @@ LOCAL_SRC_FILES:= \ yahfa/HookMain.c \ yahfa/trampoline.c \ java_hook/java_hook.cpp \ - inject/framework_hook.cpp \ - inject/config_manager.cpp + inject/framework_hook.cpp include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/Core/jni/main/inject/config_manager.cpp b/Core/jni/main/inject/config_manager.cpp deleted file mode 100644 index 8b8a54be..00000000 --- a/Core/jni/main/inject/config_manager.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Created by Solo on 2019/1/27. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "config_manager.h" - -#define BLACK_LIST_PATH "/data/misc/riru/modules/edxposed/blacklist/" -#define WHITE_LIST_PATH "/data/misc/riru/modules/edxposed/whitelist/" -#define USE_WHITE_LIST "/data/misc/riru/modules/edxposed/usewhitelist" -#define GLOBAL_MODE "/data/misc/riru/modules/edxposed/forceglobal" -#define DYNAMIC_MODULES "/data/misc/riru/modules/edxposed/dynamicmodules" - -static char package_name[256]; -static bool dynamic_modules = false; -static bool inited = false; - -void initOnce() { - if (!inited) { - dynamic_modules = access(DYNAMIC_MODULES, F_OK) == 0; - inited = true; - } -} - -// default is true -int is_app_need_hook(JNIEnv *env, jstring appDataDir) { - if (!appDataDir) { - LOGW("appDataDir is null"); - return 1; - } - const char *app_data_dir = env->GetStringUTFChars(appDataDir, nullptr); - int user = 0; - if (sscanf(app_data_dir, "/data/%*[^/]/%d/%s", &user, package_name) != 2) { - if (sscanf(app_data_dir, "/data/%*[^/]/%s", package_name) != 1) { - package_name[0] = '\0'; - LOGW("can't parse %s", app_data_dir); - return 1; - } - } - env->ReleaseStringUTFChars(appDataDir, app_data_dir); - if (strcmp(package_name, "com.solohsu.android.edxp.manager") == 0) { - // always hook installer app - return 1; - } - bool use_white_list = access(USE_WHITE_LIST, F_OK) == 0; - bool white_list_exists = access(WHITE_LIST_PATH, F_OK) == 0; - bool black_list_exists = access(BLACK_LIST_PATH, F_OK) == 0; - if (use_white_list && white_list_exists) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, WHITE_LIST_PATH "%s", package_name); - int res = access(path, F_OK) == 0; - LOGD("use whitelist, res=%d", res); - return res; - } else if (!use_white_list && black_list_exists) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, BLACK_LIST_PATH "%s", package_name); - int res = access(path, F_OK) != 0; - LOGD("use blacklist, res=%d", res); - return res; - } else { - LOGD("use nonlist, res=%d", 1); - return 1; - } -} - -bool is_dynamic_modules() { - initOnce(); - return dynamic_modules; -} diff --git a/Core/jni/main/inject/config_manager.h b/Core/jni/main/inject/config_manager.h deleted file mode 100644 index 622be4cd..00000000 --- a/Core/jni/main/inject/config_manager.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Created by Solo on 2019/1/27. -// - -#ifndef EDXPOSED_CONFIG_MANAGER_H -#define EDXPOSED_CONFIG_MANAGER_H - -int is_app_need_hook(JNIEnv *env, jstring appDataDir); - -bool is_dynamic_modules(); - -#endif //EDXPOSED_CONFIG_MANAGER_H diff --git a/Core/jni/main/inject/framework_hook.cpp b/Core/jni/main/inject/framework_hook.cpp index e4beefa4..66cb9e24 100644 --- a/Core/jni/main/inject/framework_hook.cpp +++ b/Core/jni/main/inject/framework_hook.cpp @@ -5,7 +5,6 @@ #include #include "framework_hook.h" #include "include/misc.h" -#include "config_manager.h" #define SYSTEM_SERVER_DATA_DIR "/data/user/0/android" @@ -42,21 +41,15 @@ void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities, jlong effectiveCapabilities) { sAppDataDir = env->NewStringUTF(SYSTEM_SERVER_DATA_DIR); - if (!is_app_need_hook(env, sAppDataDir)) { - return; - } prepareJavaEnv(env); // jump to java code - findAndCall(env, "forkSystemServerPre", "(II[II[[IJJZ)V", uid, gid, gids, runtime_flags, rlimits, - permittedCapabilities, effectiveCapabilities, is_dynamic_modules()); + findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, rlimits, + permittedCapabilities, effectiveCapabilities); } int onNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { - if (!is_app_need_hook(env, sAppDataDir)) { - return 0; - } prepareJavaEnv(env); // only do work in child since findAndCall would print log findAndCall(env, "forkSystemServerPost", "(I)V", res); @@ -81,22 +74,16 @@ void onNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jstring instructionSet, jstring appDataDir) { sAppDataDir = appDataDir; - if (!is_app_need_hook(env, appDataDir)) { - return; - } prepareJavaEnv(env); findAndCall(env, "forkAndSpecializePre", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)V", + "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V", uid, gid, gids, runtime_flags, rlimits, _mount_external, se_info, se_name, fdsToClose, fdsToIgnore, - is_child_zygote, instructionSet, appDataDir, is_dynamic_modules()); + is_child_zygote, instructionSet, appDataDir); } int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { - if (!is_app_need_hook(env, sAppDataDir)) { - return 0; - } prepareJavaEnv(env); findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;)V", res, sAppDataDir); } else {