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;
import com.elderdrivers.riru.edxp.util.Utils;
import de.robv.android.xposed.XposedHelpers;
public class 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 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.deopt.PrebuiltMethodsDeopter;
import com.elderdrivers.riru.edxp.framework.Zygote;
import com.elderdrivers.riru.edxp.util.ProcessUtils;
import com.elderdrivers.riru.edxp.util.Utils;
@ -87,16 +86,12 @@ public class BlackWhiteListProxy extends BaseProxy {
// loadModules once for all child processes of zygote
// TODO maybe just save initZygote callbacks and call them when whitelisted process forked?
mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
}
private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) {
ConfigManager.appDataDir = appDataDir;
ConfigManager.niceName = niceName;
final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled();
if (!isDynamicModulesMode) {
Zygote.reopenFilesAfterFork();
}
mRouter.onEnterChildProcess();
if (!checkNeedHook(appDataDir, niceName)) {
// 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.deopt.PrebuiltMethodsDeopter;
import com.elderdrivers.riru.edxp.framework.Zygote;
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
@ -27,7 +26,6 @@ public class NormalProxy extends BaseProxy {
mRouter.installBootstrapHooks(false);
// only load modules for secondary zygote
mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
}
public void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
@ -35,7 +33,6 @@ public class NormalProxy extends BaseProxy {
ConfigManager.appDataDir = appDataDir;
ConfigManager.niceName = niceName;
mRouter.prepare(false);
Zygote.reopenFilesAfterFork();
mRouter.onEnterChildProcess();
// load modules for each app process on its forked if dynamic modules mode is on
mRouter.loadModulesSafely(false);
@ -57,7 +54,6 @@ public class NormalProxy extends BaseProxy {
// because if not global hooks installed in initZygote might not be
// propagated to processes not forked via forkAndSpecialize
mRouter.loadModulesSafely(true);
Zygote.closeFilesBeforeFork();
}
public void forkSystemServerPost(int pid) {
@ -65,7 +61,6 @@ public class NormalProxy extends BaseProxy {
ConfigManager.appDataDir = getDataPathPrefix() + "android";
ConfigManager.niceName = "system_server";
mRouter.prepare(true);
Zygote.reopenFilesAfterFork();
mRouter.onEnterChildProcess();
// reload module list if dynamic mode is on
mRouter.loadModulesSafely(false);

View File

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

View File

@ -21,20 +21,26 @@ namespace edxp {
static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:"
"/system/framework/eddalvikdx.jar:"
"/system/framework/eddexmaker.jar";
static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main";
static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker";
static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook";
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 kLibRuntimeBasePath = std::string(LP_SELECT("/apex/com.android.runtime/lib/",
"/apex/com.android.runtime/lib64/"));
static const auto kLibRuntimeBasePath = std::string(
LP_SELECT("/apex/com.android.runtime/lib/", "/apex/com.android.runtime/lib64/"));
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 kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so";
static const auto kLibFwPath = kLibBasePath + "libandroidfw.so";
static const auto kLibDlPath = kLibBasePath + "libdl.so";
static const auto kLibFwkPath = kLibBasePath + kLibFwkName;
inline const char *const BoolToString(bool b) {
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/gc/heap.h"
#include "art/runtime/hidden_api.h"
#include "framework/fd_utils.h"
namespace edxp {
static bool installed = false;
static bool art_hooks_installed = false;
static bool fwk_hooks_installed = false;
static HookFunType hook_func = nullptr;
void InstallArtHooks(void *art_handle);
void InstallFwkHooks(void *fwk_handle);
CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags,
const void *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);
}
return handle;
@ -69,6 +73,9 @@ namespace edxp {
ScopedDlHandle art_handle(kLibArtPath.c_str());
InstallArtHooks(art_handle.Get());
}
ScopedDlHandle fwk_handle(kLibFwkPath.c_str());
InstallFwkHooks(fwk_handle.Get());
}
void InstallArtHooks(void *art_handle) {
@ -85,5 +92,12 @@ namespace edxp {
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
EDXP_VERSION="0.4.4.1_alpha (4410)"
EDXP_VERSION="0.4.4.2_alpha (4420)"
ANDROID_SDK=`getprop ro.build.version.sdk`
BUILD_DESC=`getprop ro.build.description`
PRODUCT=`getprop ro.build.product`