Filter process earlier

This commit is contained in:
LoveSy 2020-11-12 18:47:24 +08:00 committed by solohsu
parent 00363c31db
commit 3702bf333b
6 changed files with 124 additions and 173 deletions

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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__)

View File

@ -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_;
};

View File

@ -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

View File

@ -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);
};
}