Filter process earlier
This commit is contained in:
parent
00363c31db
commit
3702bf333b
|
|
@ -6,7 +6,6 @@ import android.os.Process;
|
|||
import com.elderdrivers.riru.common.KeepAll;
|
||||
import com.elderdrivers.riru.edxp.common.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||
import com.elderdrivers.riru.edxp.framework.ProcessHelper;
|
||||
import com.elderdrivers.riru.edxp.util.Utils;
|
||||
|
||||
import java.security.AccessController;
|
||||
|
|
@ -16,8 +15,6 @@ import java.util.Iterator;
|
|||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.elderdrivers.riru.edxp.proxy.BaseProxy.onBlackListed;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public class Main implements KeepAll {
|
||||
|
||||
|
|
@ -40,9 +37,6 @@ public class Main implements KeepAll {
|
|||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||
boolean startChildZygote, String instructionSet,
|
||||
String appDataDir) {
|
||||
if (isBlackListedProcess(uid)) {
|
||||
return;
|
||||
}
|
||||
final EdxpImpl edxp = getEdxpImpl();
|
||||
if (edxp == null || !edxp.isInitialized()) {
|
||||
return;
|
||||
|
|
@ -67,10 +61,6 @@ public class Main implements KeepAll {
|
|||
}
|
||||
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
|
||||
if (isBlackListedProcess(Process.myUid())) {
|
||||
onBlackListed();
|
||||
return;
|
||||
}
|
||||
final EdxpImpl edxp = getEdxpImpl();
|
||||
if (edxp == null || !edxp.isInitialized()) {
|
||||
return;
|
||||
|
|
@ -159,11 +149,4 @@ public class Main implements KeepAll {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO do this earlier?
|
||||
private static boolean isBlackListedProcess(int uid) {
|
||||
return ProcessHelper.isIsolated(uid)
|
||||
|| ProcessHelper.isRELROUpdater(uid)
|
||||
|| ProcessHelper.isWebViewZygote(uid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,96 +0,0 @@
|
|||
package com.elderdrivers.riru.edxp.framework;
|
||||
|
||||
import android.os.Process;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.annotation.ApiSensitive;
|
||||
import de.robv.android.xposed.annotation.Level;
|
||||
|
||||
@ApiSensitive(Level.MIDDLE)
|
||||
public class ProcessHelper {
|
||||
|
||||
static {
|
||||
// WEBVIEW_ZYGOTE_UID differ among versions
|
||||
WEBVIEW_ZYGOTE_UID = XposedHelpers.getStaticIntField(android.os.Process.class, "WEBVIEW_ZYGOTE_UID");
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the UID/GID for the shared RELRO file updater process.
|
||||
*/
|
||||
public static final int SHARED_RELRO_UID = 1037;
|
||||
|
||||
/**
|
||||
* Defines the UID/GID for the WebView zygote process.
|
||||
*/
|
||||
public static final int WEBVIEW_ZYGOTE_UID;
|
||||
|
||||
/**
|
||||
* First uid used for fully isolated sandboxed processes (with no permissions of their own)
|
||||
*/
|
||||
public static final int FIRST_ISOLATED_UID = 99000;
|
||||
/**
|
||||
* Last uid used for fully isolated sandboxed processes (with no permissions of their own)
|
||||
*/
|
||||
public static final int LAST_ISOLATED_UID = 99999;
|
||||
|
||||
/**
|
||||
* First uid used for fully isolated sandboxed processes spawned from an app zygote
|
||||
*/
|
||||
public static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
||||
/**
|
||||
* Number of UIDs we allocate per application zygote
|
||||
*/
|
||||
public static final int NUM_UIDS_PER_APP_ZYGOTE = 100;
|
||||
/**
|
||||
* Last uid used for fully isolated sandboxed processes spawned from an app zygote
|
||||
*/
|
||||
public static final int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
|
||||
|
||||
/**
|
||||
* Range of uids allocated for a user.
|
||||
*/
|
||||
public static final int PER_USER_RANGE = 100000;
|
||||
|
||||
// @see UserHandle#getAppId(int)
|
||||
public static int getAppId(int uid) {
|
||||
return uid % PER_USER_RANGE;
|
||||
}
|
||||
|
||||
public static boolean isRELROUpdater(int uid) {
|
||||
return getAppId(uid) == SHARED_RELRO_UID;
|
||||
}
|
||||
|
||||
public static boolean isWebViewZygote(int uid) {
|
||||
return getAppId(uid) == WEBVIEW_ZYGOTE_UID;
|
||||
}
|
||||
|
||||
public static boolean isIsolated(int uid) {
|
||||
return (boolean) XposedHelpers.callStaticMethod(
|
||||
Process.class, "isIsolated", uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a UID belongs to a regular app. *Note* "Not a regular app" does not mean
|
||||
* "it's system", because of isolated UIDs. Use {@link #isCore} for that.
|
||||
*/
|
||||
public static boolean isApp(int uid) {
|
||||
if (uid > 0) {
|
||||
final int appId = getAppId(uid);
|
||||
return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a UID belongs to a system core component or not.
|
||||
*/
|
||||
public static boolean isCore(int uid) {
|
||||
if (uid >= 0) {
|
||||
final int appId = getAppId(uid);
|
||||
return appId < Process.FIRST_APPLICATION_UID;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#define LOGE(...)
|
||||
#else
|
||||
#define LOG_TAG "EdXposed"
|
||||
#ifdef DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -103,3 +103,31 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) {
|
|||
env->RegisterNatives(class, methods, size); \
|
||||
if (ClearException(env)) LOGE("RegisterNatives " #class);
|
||||
|
||||
class JUTFString {
|
||||
public:
|
||||
inline JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) {
|
||||
}
|
||||
|
||||
inline JUTFString(JNIEnv *env, jstring jstr, const char *default_cstr) : env_(env),
|
||||
jstr_(jstr) {
|
||||
if (env_ && jstr_) cstr_ = env_->GetStringUTFChars(jstr, nullptr);
|
||||
else cstr_ = default_cstr;
|
||||
}
|
||||
|
||||
inline operator const char *() const { return cstr_; }
|
||||
|
||||
inline operator const std::string() const { return cstr_; }
|
||||
|
||||
inline operator const bool() const { return cstr_ != nullptr; }
|
||||
|
||||
inline auto get() const { return cstr_; }
|
||||
|
||||
inline ~JUTFString() {
|
||||
if (env_ && jstr_) env_->ReleaseStringUTFChars(jstr_, cstr_);
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv *env_;
|
||||
jstring jstr_;
|
||||
const char *cstr_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,27 +22,12 @@
|
|||
#pragma clang diagnostic ignored "-Wunused-value"
|
||||
|
||||
namespace edxp {
|
||||
|
||||
Context *Context::instance_ = nullptr;
|
||||
|
||||
Context *Context::GetInstance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new Context();
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool Context::IsInitialized() const {
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Variant Context::GetVariant() const {
|
||||
return variant_;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE jobject Context::GetCurrentClassLoader() const {
|
||||
return inject_class_loader_;
|
||||
}
|
||||
constexpr int FIRST_ISOLATED_UID = 99000;
|
||||
constexpr int LAST_ISOLATED_UID = 99999;
|
||||
constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
||||
constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
|
||||
constexpr int SHARED_RELRO_UID = 1037;
|
||||
constexpr int PER_USER_RANGE = 100000;
|
||||
|
||||
void Context::CallPostFixupStaticTrampolinesCallback(void *class_ptr, jmethodID callback_mid) {
|
||||
if (UNLIKELY(!callback_mid || !class_linker_class_)) {
|
||||
|
|
@ -188,6 +173,28 @@ namespace edxp {
|
|||
LoadDexAndInit(env, kInjectDexPath);
|
||||
}
|
||||
|
||||
void Context::ReleaseJavaEnv(JNIEnv *env) {
|
||||
if (UNLIKELY(!instance_)) return;
|
||||
initialized_ = false;
|
||||
if (entry_class_) {
|
||||
env->DeleteGlobalRef(entry_class_);
|
||||
entry_class_ = nullptr;
|
||||
}
|
||||
if (class_linker_class_) {
|
||||
env->DeleteGlobalRef(class_linker_class_);
|
||||
class_linker_class_ = nullptr;
|
||||
}
|
||||
if (inject_class_loader_) {
|
||||
env->DeleteGlobalRef(inject_class_loader_);
|
||||
inject_class_loader_ = nullptr;
|
||||
}
|
||||
app_data_dir_ = nullptr;
|
||||
nice_name_ = nullptr;
|
||||
vm_ = nullptr;
|
||||
pre_fixup_static_mid_ = nullptr;
|
||||
post_fixup_static_mid_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline void Context::FindAndCall(JNIEnv *env, const char *method_name,
|
||||
const char *method_sig, ...) const {
|
||||
|
|
@ -206,26 +213,6 @@ namespace edxp {
|
|||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE JavaVM *Context::GetJavaVM() const {
|
||||
return vm_;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Context::SetAppDataDir(jstring app_data_dir) {
|
||||
app_data_dir_ = app_data_dir;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE jstring Context::GetAppDataDir() const {
|
||||
return app_data_dir_;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Context::SetNiceName(jstring nice_name) {
|
||||
nice_name_ = nice_name;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE jstring Context::GetNiceName() const {
|
||||
return nice_name_;
|
||||
}
|
||||
|
||||
void
|
||||
Context::OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid,
|
||||
jintArray gids,
|
||||
|
|
@ -252,6 +239,33 @@ namespace edxp {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Context::ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid,
|
||||
jboolean is_child_zygote) {
|
||||
const auto app_id = uid % PER_USER_RANGE;
|
||||
const JUTFString package_name(env, nice_name, "UNKNOWN");
|
||||
bool skip = false;
|
||||
if (is_child_zygote) {
|
||||
skip = true;
|
||||
LOGW("skip injecting into %s because it's a child zygote", package_name.get());
|
||||
}
|
||||
|
||||
if ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) ||
|
||||
(app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) ||
|
||||
app_id == SHARED_RELRO_UID) {
|
||||
skip = true;
|
||||
LOGW("skip injecting into %s because it's isolated", package_name.get());
|
||||
}
|
||||
|
||||
// TODO(yujincheng08): check whitelist/blacklist.
|
||||
const JUTFString dir(env, data_dir);
|
||||
if(!dir || !ConfigManager::GetInstance()->IsAppNeedHook(dir)) {
|
||||
skip = true;
|
||||
LOGW("skip injecting xposed into %s because it's whitelisted/blacklisted",
|
||||
package_name.get());
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
|
||||
jint uid, jint gid,
|
||||
jintArray gids,
|
||||
|
|
@ -265,21 +279,32 @@ namespace edxp {
|
|||
jboolean is_child_zygote,
|
||||
jstring instruction_set,
|
||||
jstring app_data_dir) {
|
||||
skip_ = ShouldSkipInject(env, nice_name, app_data_dir, uid, is_child_zygote);
|
||||
app_data_dir_ = app_data_dir;
|
||||
nice_name_ = nice_name;
|
||||
PrepareJavaEnv(env);
|
||||
FindAndCall(env, "forkAndSpecializePre",
|
||||
"(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, nice_name, fds_to_close, fds_to_ignore,
|
||||
is_child_zygote, instruction_set, app_data_dir);
|
||||
if(!skip_) {
|
||||
FindAndCall(env, "forkAndSpecializePre",
|
||||
"(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, nice_name, fds_to_close, fds_to_ignore,
|
||||
is_child_zygote, instruction_set, app_data_dir);
|
||||
}
|
||||
}
|
||||
|
||||
int Context::OnNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||
if (res == 0) {
|
||||
PrepareJavaEnv(env);
|
||||
FindAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;Ljava/lang/String;)V",
|
||||
res, app_data_dir_, nice_name_);
|
||||
const JUTFString package_name(env, nice_name_);
|
||||
if (!skip_) {
|
||||
PrepareJavaEnv(env);
|
||||
FindAndCall(env, "forkAndSpecializePost",
|
||||
"(ILjava/lang/String;Ljava/lang/String;)V",
|
||||
res, app_data_dir_, nice_name_);
|
||||
LOGD("injected xposed into %s", package_name.get());
|
||||
} else {
|
||||
ReleaseJavaEnv(env);
|
||||
LOGD("skipped %s", package_name.get());
|
||||
}
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||
|
|
|
|||
|
|
@ -18,9 +18,14 @@ namespace edxp {
|
|||
class Context {
|
||||
|
||||
public:
|
||||
static Context *GetInstance();
|
||||
inline static auto GetInstance() {
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new Context();
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
jobject GetCurrentClassLoader() const;
|
||||
inline auto GetCurrentClassLoader() const { return inject_class_loader_; }
|
||||
|
||||
void CallOnPreFixupStaticTrampolines(void *class_ptr);
|
||||
|
||||
|
|
@ -30,15 +35,15 @@ namespace edxp {
|
|||
|
||||
void FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const;
|
||||
|
||||
JavaVM *GetJavaVM() const;
|
||||
inline auto *GetJavaVM() const { return vm_; }
|
||||
|
||||
void SetAppDataDir(jstring app_data_dir);
|
||||
inline void SetAppDataDir(jstring app_data_dir) { app_data_dir_ = app_data_dir; }
|
||||
|
||||
void SetNiceName(jstring nice_name);
|
||||
inline void SetNiceName(jstring nice_name) { nice_name_ = nice_name; }
|
||||
|
||||
jstring GetAppDataDir() const;
|
||||
inline auto GetAppDataDir() const { return app_data_dir_; }
|
||||
|
||||
jstring GetNiceName() const;
|
||||
inline auto GetNiceName() const { return nice_name_; }
|
||||
|
||||
jclass FindClassFromLoader(JNIEnv *env, const char *className) const;
|
||||
|
||||
|
|
@ -58,12 +63,12 @@ namespace edxp {
|
|||
jlong permitted_capabilities,
|
||||
jlong effective_capabilities);
|
||||
|
||||
bool IsInitialized() const;
|
||||
inline auto IsInitialized() const { return initialized_; }
|
||||
|
||||
Variant GetVariant() const;
|
||||
inline auto GetVariant() const { return variant_; };
|
||||
|
||||
private:
|
||||
static Context *instance_;
|
||||
inline static Context *instance_;
|
||||
bool initialized_ = false;
|
||||
Variant variant_ = NONE;
|
||||
jobject inject_class_loader_ = nullptr;
|
||||
|
|
@ -74,6 +79,7 @@ namespace edxp {
|
|||
jclass class_linker_class_ = nullptr;
|
||||
jmethodID pre_fixup_static_mid_ = nullptr;
|
||||
jmethodID post_fixup_static_mid_ = nullptr;
|
||||
bool skip_ = false;
|
||||
|
||||
Context() {}
|
||||
|
||||
|
|
@ -84,6 +90,11 @@ namespace edxp {
|
|||
jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const;
|
||||
|
||||
void CallPostFixupStaticTrampolinesCallback(void *class_ptr, jmethodID mid);
|
||||
|
||||
static bool ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid,
|
||||
jboolean is_child_zygote);
|
||||
|
||||
void ReleaseJavaEnv(JNIEnv *env);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue