Use inline hook to append allow-across-fork file whitelist

This commit is contained in:
solohsu 2019-06-14 10:53:34 +08:00
parent c4978b7344
commit 7eaae6d898
8 changed files with 76 additions and 17 deletions

View File

@ -1,5 +1,9 @@
package com.elderdrivers.riru.edxp.framework; package com.elderdrivers.riru.edxp.framework;
import com.elderdrivers.riru.edxp.util.Utils;
import de.robv.android.xposed.XposedHelpers;
public class Zygote { public class Zygote {
// prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote // prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote
@ -8,4 +12,12 @@ public class Zygote {
public static native void reopenFilesAfterFork(); public static native void reopenFilesAfterFork();
public static void allowFileAcrossFork(String path) {
try {
Class zygote = XposedHelpers.findClass("com.android.internal.os.Zygote", null);
XposedHelpers.callStaticMethod(zygote, "nativeAllowFileAcrossFork", path);
} catch (Throwable throwable) {
Utils.logE("error when allowFileAcrossFork", throwable);
}
}
} }

View File

@ -4,7 +4,6 @@ import android.text.TextUtils;
import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
import com.elderdrivers.riru.edxp.framework.Zygote;
import com.elderdrivers.riru.edxp.util.ProcessUtils; import com.elderdrivers.riru.edxp.util.ProcessUtils;
import com.elderdrivers.riru.edxp.util.Utils; import com.elderdrivers.riru.edxp.util.Utils;
@ -87,16 +86,12 @@ public class BlackWhiteListProxy extends BaseProxy {
// loadModules once for all child processes of zygote // loadModules once for all child processes of zygote
// TODO maybe just save initZygote callbacks and call them when whitelisted process forked? // TODO maybe just save initZygote callbacks and call them when whitelisted process forked?
mRouter.loadModulesSafely(true); mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
} }
private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) {
ConfigManager.appDataDir = appDataDir; ConfigManager.appDataDir = appDataDir;
ConfigManager.niceName = niceName; ConfigManager.niceName = niceName;
final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled();
if (!isDynamicModulesMode) {
Zygote.reopenFilesAfterFork();
}
mRouter.onEnterChildProcess(); mRouter.onEnterChildProcess();
if (!checkNeedHook(appDataDir, niceName)) { if (!checkNeedHook(appDataDir, niceName)) {
// if is blacklisted, just stop here // if is blacklisted, just stop here

View File

@ -2,7 +2,6 @@ package com.elderdrivers.riru.edxp.proxy;
import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter;
import com.elderdrivers.riru.edxp.framework.Zygote;
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
@ -27,7 +26,6 @@ public class NormalProxy extends BaseProxy {
mRouter.installBootstrapHooks(false); mRouter.installBootstrapHooks(false);
// only load modules for secondary zygote // only load modules for secondary zygote
mRouter.loadModulesSafely(true); mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
} }
public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { public void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
@ -35,7 +33,6 @@ public class NormalProxy extends BaseProxy {
ConfigManager.appDataDir = appDataDir; ConfigManager.appDataDir = appDataDir;
ConfigManager.niceName = niceName; ConfigManager.niceName = niceName;
mRouter.prepare(false); mRouter.prepare(false);
Zygote.reopenFilesAfterFork();
mRouter.onEnterChildProcess(); mRouter.onEnterChildProcess();
// load modules for each app process on its forked if dynamic modules mode is on // load modules for each app process on its forked if dynamic modules mode is on
mRouter.loadModulesSafely(false); mRouter.loadModulesSafely(false);
@ -57,7 +54,6 @@ public class NormalProxy extends BaseProxy {
// because if not global hooks installed in initZygote might not be // because if not global hooks installed in initZygote might not be
// propagated to processes not forked via forkAndSpecialize // propagated to processes not forked via forkAndSpecialize
mRouter.loadModulesSafely(true); mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
} }
public void forkSystemServerPost(int pid) { public void forkSystemServerPost(int pid) {
@ -65,7 +61,6 @@ public class NormalProxy extends BaseProxy {
ConfigManager.appDataDir = getDataPathPrefix() + "android"; ConfigManager.appDataDir = getDataPathPrefix() + "android";
ConfigManager.niceName = "system_server"; ConfigManager.niceName = "system_server";
mRouter.prepare(true); mRouter.prepare(true);
Zygote.reopenFilesAfterFork();
mRouter.onEnterChildProcess(); mRouter.onEnterChildProcess();
// reload module list if dynamic mode is on // reload module list if dynamic mode is on
mRouter.loadModulesSafely(false); mRouter.loadModulesSafely(false);

View File

@ -3,10 +3,10 @@ import org.gradle.internal.os.OperatingSystem
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
version "v0.4.4.1_alpha" version "v0.4.4.2_alpha"
ext { ext {
versionCode = "4410" versionCode = "4420"
module_name = "EdXposed" module_name = "EdXposed"
jar_dest_dir = "${projectDir}/template_override/system/framework/" jar_dest_dir = "${projectDir}/template_override/system/framework/"
is_windows = OperatingSystem.current().isWindows() is_windows = OperatingSystem.current().isWindows()

View File

@ -21,20 +21,26 @@ namespace edxp {
static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:" static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:"
"/system/framework/eddalvikdx.jar:" "/system/framework/eddalvikdx.jar:"
"/system/framework/eddexmaker.jar"; "/system/framework/eddexmaker.jar";
static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main";
static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker";
static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook"; static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook";
static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall";
static constexpr auto kLibArtName = "libart.so";
static constexpr auto kLibFwkName = "libandroid_runtime.so";
static const auto kLibBasePath = std::string(LP_SELECT("/system/lib/", "/system/lib64/")); static const auto kLibBasePath = std::string(LP_SELECT("/system/lib/", "/system/lib64/"));
static const auto kLibRuntimeBasePath = std::string(LP_SELECT("/apex/com.android.runtime/lib/", static const auto kLibRuntimeBasePath = std::string(
"/apex/com.android.runtime/lib64/")); LP_SELECT("/apex/com.android.runtime/lib/", "/apex/com.android.runtime/lib64/"));
static const auto kLibArtPath = static const auto kLibArtPath =
(GetAndroidApiLevel() >= ANDROID_Q ? kLibRuntimeBasePath : kLibBasePath) + "libart.so"; (GetAndroidApiLevel() >= ANDROID_Q ? kLibRuntimeBasePath : kLibBasePath) + kLibArtName;
static const auto kLibWhalePath = kLibBasePath + "libwhale.edxp.so"; static const auto kLibWhalePath = kLibBasePath + "libwhale.edxp.so";
static const auto kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so"; static const auto kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so";
static const auto kLibFwPath = kLibBasePath + "libandroidfw.so"; static const auto kLibFwPath = kLibBasePath + "libandroidfw.so";
static const auto kLibDlPath = kLibBasePath + "libdl.so"; static const auto kLibDlPath = kLibBasePath + "libdl.so";
static const auto kLibFwkPath = kLibBasePath + kLibFwkName;
inline const char *const BoolToString(bool b) { inline const char *const BoolToString(bool b) {
return b ? "true" : "false"; return b ? "true" : "false";

View File

@ -0,0 +1,37 @@
#pragma once
#include <android-base/strings.h>
#include "base/object.h"
namespace android {
// Static whitelist of open paths that the zygote is allowed to keep open.
static const char *kPathWhitelist[] = {
"/data/app/",
"/data/app-private/"
};
class FileDescriptorWhitelist : public edxp::HookedObject {
public:
FileDescriptorWhitelist(void *thiz) : HookedObject(thiz) {}
static void Setup(void *handle, HookFunType hook_func) {
HOOK_FUNC(IsAllowed,
"_ZNK23FileDescriptorWhitelist9IsAllowedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE");
}
private:
CREATE_HOOK_STUB_ENTRIES(bool, IsAllowed, void *thiz, const std::string &path) {
for (const auto &whitelist_path : kPathWhitelist) {
if (android::base::StartsWith(path, whitelist_path))
return true;
}
return IsAllowedBackup(thiz, path);
}
};
}

View File

@ -16,19 +16,23 @@
#include "art/runtime/class_linker.h" #include "art/runtime/class_linker.h"
#include "art/runtime/gc/heap.h" #include "art/runtime/gc/heap.h"
#include "art/runtime/hidden_api.h" #include "art/runtime/hidden_api.h"
#include "framework/fd_utils.h"
namespace edxp { namespace edxp {
static bool installed = false; static bool installed = false;
static bool art_hooks_installed = false; static bool art_hooks_installed = false;
static bool fwk_hooks_installed = false;
static HookFunType hook_func = nullptr; static HookFunType hook_func = nullptr;
void InstallArtHooks(void *art_handle); void InstallArtHooks(void *art_handle);
void InstallFwkHooks(void *fwk_handle);
CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags, CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags,
const void *caller) { const void *caller) {
void *handle = mydlopenBackup(file_name, flags, caller); void *handle = mydlopenBackup(file_name, flags, caller);
if (std::string(file_name).find("libart.so") != std::string::npos) { if (std::string(file_name).find(kLibArtName) != std::string::npos) {
InstallArtHooks(handle); InstallArtHooks(handle);
} }
return handle; return handle;
@ -69,6 +73,9 @@ namespace edxp {
ScopedDlHandle art_handle(kLibArtPath.c_str()); ScopedDlHandle art_handle(kLibArtPath.c_str());
InstallArtHooks(art_handle.Get()); InstallArtHooks(art_handle.Get());
} }
ScopedDlHandle fwk_handle(kLibFwkPath.c_str());
InstallFwkHooks(fwk_handle.Get());
} }
void InstallArtHooks(void *art_handle) { void InstallArtHooks(void *art_handle) {
@ -85,5 +92,12 @@ namespace edxp {
LOGI("ART hooks installed"); LOGI("ART hooks installed");
} }
void InstallFwkHooks(void *fwk_handle) {
if (fwk_hooks_installed) {
return;
}
android::FileDescriptorWhitelist::Setup(fwk_handle, hook_func);
}
} }

View File

@ -1,6 +1,6 @@
#!/system/bin/sh #!/system/bin/sh
EDXP_VERSION="0.4.4.1_alpha (4410)" EDXP_VERSION="0.4.4.2_alpha (4420)"
ANDROID_SDK=`getprop ro.build.version.sdk` ANDROID_SDK=`getprop ro.build.version.sdk`
BUILD_DESC=`getprop ro.build.description` BUILD_DESC=`getprop ro.build.description`
PRODUCT=`getprop ro.build.product` PRODUCT=`getprop ro.build.product`