Use inline hook to append allow-across-fork file whitelist
This commit is contained in:
parent
c4978b7344
commit
7eaae6d898
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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`
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue