[core] Native request binder
This commit is contained in:
parent
c65af4c4b5
commit
0ec8959235
|
|
@ -3,7 +3,9 @@ package io.github.lsposed.lspd.service;
|
||||||
interface ILSPApplicationService {
|
interface ILSPApplicationService {
|
||||||
void registerHeartBeat(IBinder handle) = 1;
|
void registerHeartBeat(IBinder handle) = 1;
|
||||||
|
|
||||||
IBinder requestModuleBinder() = 2;
|
int getVariant() = 2;
|
||||||
|
|
||||||
IBinder requestManagerBinder() = 3;
|
IBinder requestModuleBinder() = 3;
|
||||||
|
|
||||||
|
IBinder requestManagerBinder() = 4;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,10 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) {
|
||||||
env->CallVoidMethod(obj, __VA_ARGS__); \
|
env->CallVoidMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
|
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
|
#define JNI_CallBooleanMethod(env, obj, ...) \
|
||||||
|
env->CallBooleanMethod(obj, __VA_ARGS__); \
|
||||||
|
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_GetStaticFieldID(env, class, name, sig) \
|
#define JNI_GetStaticFieldID(env, class, name, sig) \
|
||||||
env->GetStaticFieldID(class, name, sig); \
|
env->GetStaticFieldID(class, name, sig); \
|
||||||
if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig)
|
if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
#include <JNIHelper.h>
|
#include "JNIHelper.h"
|
||||||
#include "jni/config_manager.h"
|
#include "jni/config_manager.h"
|
||||||
#include "jni/art_class_linker.h"
|
#include "jni/art_class_linker.h"
|
||||||
#include "jni/yahfa.h"
|
#include "jni/yahfa.h"
|
||||||
|
|
@ -133,23 +133,23 @@ namespace lspd {
|
||||||
RegisterPendingHooks(env);
|
RegisterPendingHooks(env);
|
||||||
RegisterNativeAPI(env);
|
RegisterNativeAPI(env);
|
||||||
|
|
||||||
variant_ = Variant(ConfigManager::GetInstance()->GetVariant());
|
// variant_ = Variant(ConfigManager::GetInstance()->GetVariant());
|
||||||
LOGI("LSP Variant: %d", variant_);
|
// LOGI("LSP Variant: %d", variant_);
|
||||||
|
//
|
||||||
if (variant_ == SANDHOOK) {
|
// if (variant_ == SANDHOOK) {
|
||||||
//for SandHook variant
|
// //for SandHook variant
|
||||||
ScopedLocalRef sandhook_class(env, FindClassFromCurrentLoader(env, kSandHookClassName));
|
// ScopedLocalRef sandhook_class(env, FindClassFromCurrentLoader(env, kSandHookClassName));
|
||||||
ScopedLocalRef nevercall_class(env,
|
// ScopedLocalRef nevercall_class(env,
|
||||||
FindClassFromCurrentLoader(env,
|
// FindClassFromCurrentLoader(env,
|
||||||
kSandHookNeverCallClassName));
|
// kSandHookNeverCallClassName));
|
||||||
if (sandhook_class == nullptr || nevercall_class == nullptr) { // fail-fast
|
// if (sandhook_class == nullptr || nevercall_class == nullptr) { // fail-fast
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (!JNI_Load_Ex(env, sandhook_class.get(), nevercall_class.get())) {
|
// if (!JNI_Load_Ex(env, sandhook_class.get(), nevercall_class.get())) {
|
||||||
LOGE("SandHook: HookEntry class error. %d", getpid());
|
// LOGE("SandHook: HookEntry class error. %d", getpid());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass
|
||||||
|
|
@ -202,108 +202,33 @@ namespace lspd {
|
||||||
[[maybe_unused]] jobjectArray rlimits,
|
[[maybe_unused]] jobjectArray rlimits,
|
||||||
[[maybe_unused]] jlong permitted_capabilities,
|
[[maybe_unused]] jlong permitted_capabilities,
|
||||||
[[maybe_unused]] jlong effective_capabilities) {
|
[[maybe_unused]] jlong effective_capabilities) {
|
||||||
ConfigManager::SetCurrentUser(0u);
|
Service::instance()->InitService(env);
|
||||||
app_modules_list_ = ConfigManager::GetInstance()->GetAppModuleList(
|
|
||||||
"android"); // I don't think we need this, but anyway
|
|
||||||
skip_ = false;
|
|
||||||
if (!ConfigManager::GetInstance()->IsInitialized()) {
|
|
||||||
LOGE("skip injecting into android because configurations are not loaded properly");
|
|
||||||
}
|
|
||||||
if (!skip_ && app_modules_list_.empty()) {
|
|
||||||
skip_ = true;
|
|
||||||
LOGD("skip injecting into android because no module hooks it");
|
|
||||||
}
|
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||||
ConfigManager::GetInstance()->EnsurePermission("android", 1000);
|
skip_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
Context::OnNativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) {
|
Context::OnNativeForkSystemServerPost(JNIEnv *env, jint res) {
|
||||||
if (res == 0) {
|
if (res != 0) return;
|
||||||
if (!skip_) {
|
auto binder = Service::instance()->RequestBinder(env);
|
||||||
if (void *buf = mmap(nullptr, 1, PROT_READ | PROT_WRITE | PROT_EXEC,
|
if (binder) {
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, -1,
|
if (void *buf = mmap(nullptr, 1, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
0);
|
MAP_ANONYMOUS | MAP_PRIVATE, -1,
|
||||||
buf == MAP_FAILED) {
|
0);
|
||||||
skip_ = true;
|
buf == MAP_FAILED) {
|
||||||
LOGE("skip injecting into android because sepolicy was not loaded properly");
|
skip_ = true;
|
||||||
} else {
|
LOGE("skip injecting into android because sepolicy was not loaded properly");
|
||||||
munmap(buf, 1);
|
} else {
|
||||||
}
|
munmap(buf, 1);
|
||||||
}
|
}
|
||||||
LoadDex(env);
|
|
||||||
if (!skip_) {
|
|
||||||
InstallInlineHooks();
|
|
||||||
Init(env);
|
|
||||||
// only do work in child since FindAndCall would print log
|
|
||||||
FindAndCall(env, "forkSystemServerPost", "(II)V", res,
|
|
||||||
variant_);
|
|
||||||
}
|
|
||||||
InitService(*this, env);
|
|
||||||
} 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
|
|
||||||
}
|
}
|
||||||
return 0;
|
LoadDex(env);
|
||||||
}
|
if (!skip_ && binder) {
|
||||||
|
InstallInlineHooks();
|
||||||
std::tuple<bool, uid_t, std::string>
|
Init(env);
|
||||||
Context::GetAppInfoFromDir(JNIEnv *env, jstring dir, jstring nice_name) {
|
FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder);
|
||||||
uid_t uid = 0;
|
|
||||||
JUTFString app_data_dir(env, dir);
|
|
||||||
JUTFString name(env, nice_name);
|
|
||||||
if (!app_data_dir) return {false, 0, name.get()};
|
|
||||||
fs::path path(app_data_dir.get());
|
|
||||||
std::vector<std::string> splits(path.begin(), path.end());
|
|
||||||
if (splits.size() < 5u) {
|
|
||||||
LOGE("can't parse %s", path.c_str());
|
|
||||||
return {false, 0, name.get()};
|
|
||||||
}
|
}
|
||||||
const auto &uid_str = splits[3];
|
Service::instance()->HookBridge(*this, env);
|
||||||
const auto &package_name = splits[4];
|
|
||||||
try {
|
|
||||||
uid = stol(uid_str);
|
|
||||||
} catch (const std::invalid_argument &ignored) {
|
|
||||||
LOGE("can't parse %s", app_data_dir.get());
|
|
||||||
return {false, uid, {}};
|
|
||||||
}
|
|
||||||
return {true, uid, package_name};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Context::ShouldSkipInject(const std::string &package_name, uid_t user, uid_t uid,
|
|
||||||
bool info_res,
|
|
||||||
const std::function<bool()> &empty_list,
|
|
||||||
bool is_child_zygote) {
|
|
||||||
const auto app_id = uid % PER_USER_RANGE;
|
|
||||||
bool skip = false;
|
|
||||||
if (!ConfigManager::GetInstance()->IsInitialized()) {
|
|
||||||
LOGE("skip injecting into %s because configurations are not loaded properly",
|
|
||||||
package_name.c_str());
|
|
||||||
skip = true;
|
|
||||||
}
|
|
||||||
if (!skip && !info_res) {
|
|
||||||
LOGD("skip injecting into %s because it has no data dir", package_name.c_str());
|
|
||||||
skip = true;
|
|
||||||
}
|
|
||||||
if (!skip && is_child_zygote) {
|
|
||||||
skip = true;
|
|
||||||
LOGD("skip injecting into %s because it's a child zygote", package_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skip && ((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;
|
|
||||||
LOGI("skip injecting into %s because it's isolated", package_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skip && empty_list() && !ConfigManager::GetInstance()->IsInstaller(package_name)) {
|
|
||||||
skip = true;
|
|
||||||
LOGD("skip injecting xposed into %s because no module hooks it",
|
|
||||||
package_name.c_str());
|
|
||||||
}
|
|
||||||
return skip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
|
void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
|
||||||
|
|
@ -319,50 +244,50 @@ namespace lspd {
|
||||||
jboolean is_child_zygote,
|
jboolean is_child_zygote,
|
||||||
jstring instruction_set,
|
jstring instruction_set,
|
||||||
jstring app_data_dir) {
|
jstring app_data_dir) {
|
||||||
const auto&[res, user, package_name] = GetAppInfoFromDir(env, app_data_dir, nice_name);
|
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||||
app_data_dir_ = app_data_dir;
|
Service::instance()->InitService(env);
|
||||||
nice_name_ = nice_name;
|
this->uid = uid;
|
||||||
ConfigManager::SetCurrentUser(user);
|
const auto app_id = uid % PER_USER_RANGE;
|
||||||
skip_ = ShouldSkipInject(package_name, user, uid, res,
|
skip_ = false;
|
||||||
// Only obtains when needed
|
if (!skip_ && !app_data_dir) {
|
||||||
[this, &package_name = package_name]() {
|
LOGD("skip injecting into %d because it has no data dir", uid);
|
||||||
app_modules_list_ = ConfigManager::GetInstance()->GetAppModuleList(
|
skip_ = true;
|
||||||
package_name);
|
}
|
||||||
return app_modules_list_.empty();
|
if (!skip_ && is_child_zygote) {
|
||||||
}, is_child_zygote);
|
skip_ = true;
|
||||||
if (!skip_) {
|
LOGD("skip injecting into %d because it's a child zygote", uid);
|
||||||
ConfigManager::GetInstance()->EnsurePermission(package_name, uid);
|
}
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
|
||||||
|
if (!skip_ && ((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;
|
||||||
|
LOGI("skip injecting into %d because it's isolated", uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
Context::OnNativeForkAndSpecializePost(JNIEnv *env, [[maybe_unused]]jclass clazz, jint res) {
|
Context::OnNativeForkAndSpecializePost(JNIEnv *env) {
|
||||||
if (res == 0) {
|
const JUTFString process_name(env, nice_name_);
|
||||||
const JUTFString process_name(env, nice_name_);
|
auto binder = skip_? nullptr : Service::instance()->RequestBinder(env);
|
||||||
if (!skip_) {
|
if (binder) {
|
||||||
LoadDex(env);
|
LoadDex(env);
|
||||||
InstallInlineHooks();
|
InstallInlineHooks();
|
||||||
Init(env);
|
Init(env);
|
||||||
LOGD("Done prepare");
|
LOGD("Done prepare");
|
||||||
FindAndCall(env, "forkAndSpecializePost",
|
// TODO: cache this method
|
||||||
"(ILjava/lang/String;Ljava/lang/String;I)V",
|
FindAndCall(env, "forkAndSpecializePost",
|
||||||
res, app_data_dir_, nice_name_,
|
"(Ljava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V",
|
||||||
variant_);
|
app_data_dir_, nice_name_,
|
||||||
LOGD("injected xposed into %s", process_name.get());
|
binder);
|
||||||
} else {
|
LOGD("injected xposed into %s", process_name.get());
|
||||||
[[maybe_unused]] auto config_manager = ConfigManager::ReleaseInstances();
|
|
||||||
auto context = Context::ReleaseInstance();
|
|
||||||
LOGD("skipped %s", process_name.get());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// in zygote process, res is child zygote pid
|
auto context = Context::ReleaseInstance();
|
||||||
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
auto service = Service::ReleaseInstance();
|
||||||
|
LOGD("skipped %s", process_name.get());
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
@ -39,9 +39,6 @@ namespace lspd {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline static Context *GetInstance() {
|
inline static Context *GetInstance() {
|
||||||
if (!instance_) {
|
|
||||||
instance_ = std::make_unique<Context>();
|
|
||||||
}
|
|
||||||
return instance_.get();
|
return instance_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,18 +52,6 @@ namespace lspd {
|
||||||
|
|
||||||
void FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const;
|
void FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const;
|
||||||
|
|
||||||
inline auto *GetJavaVM() const { return vm_; }
|
|
||||||
|
|
||||||
inline void SetAppDataDir(jstring app_data_dir) { app_data_dir_ = app_data_dir; }
|
|
||||||
|
|
||||||
inline void SetNiceName(jstring nice_name) { nice_name_ = nice_name; }
|
|
||||||
|
|
||||||
inline auto GetAppDataDir() const { return app_data_dir_; }
|
|
||||||
|
|
||||||
inline auto GetNiceName() const { return nice_name_; }
|
|
||||||
|
|
||||||
inline auto GetAppModulesList() const { return app_modules_list_; }
|
|
||||||
|
|
||||||
inline jclass FindClassFromCurrentLoader(JNIEnv *env, std::string_view className) const {
|
inline jclass FindClassFromCurrentLoader(JNIEnv *env, std::string_view className) const {
|
||||||
return FindClassFromLoader(env, GetCurrentClassLoader(), className);
|
return FindClassFromLoader(env, GetCurrentClassLoader(), className);
|
||||||
};
|
};
|
||||||
|
|
@ -78,20 +63,18 @@ namespace lspd {
|
||||||
jintArray fds_to_ignore, jboolean is_child_zygote,
|
jintArray fds_to_ignore, jboolean is_child_zygote,
|
||||||
jstring instruction_set, jstring app_data_dir);
|
jstring instruction_set, jstring app_data_dir);
|
||||||
|
|
||||||
int OnNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res);
|
void OnNativeForkAndSpecializePost(JNIEnv *env);
|
||||||
|
|
||||||
int OnNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res);
|
void OnNativeForkSystemServerPost(JNIEnv *env, jint res);
|
||||||
|
|
||||||
void OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid,
|
void OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid,
|
||||||
jintArray gids, jint runtime_flags, jobjectArray rlimits,
|
jintArray gids, jint runtime_flags, jobjectArray rlimits,
|
||||||
jlong permitted_capabilities,
|
jlong permitted_capabilities,
|
||||||
jlong effective_capabilities);
|
jlong effective_capabilities);
|
||||||
|
|
||||||
inline auto GetVariant() const { return variant_; };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static std::unique_ptr<Context> instance_;
|
inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>();
|
||||||
Variant variant_ = NONE;
|
|
||||||
jobject inject_class_loader_ = nullptr;
|
jobject inject_class_loader_ = nullptr;
|
||||||
jclass entry_class_ = nullptr;
|
jclass entry_class_ = nullptr;
|
||||||
jstring app_data_dir_ = nullptr;
|
jstring app_data_dir_ = nullptr;
|
||||||
|
|
@ -99,9 +82,9 @@ namespace lspd {
|
||||||
JavaVM *vm_ = nullptr;
|
JavaVM *vm_ = nullptr;
|
||||||
jclass class_linker_class_ = nullptr;
|
jclass class_linker_class_ = nullptr;
|
||||||
jmethodID post_fixup_static_mid_ = nullptr;
|
jmethodID post_fixup_static_mid_ = nullptr;
|
||||||
|
jint uid = -1;
|
||||||
bool skip_ = false;
|
bool skip_ = false;
|
||||||
std::vector<signed char> dex{};
|
std::vector<signed char> dex{};
|
||||||
std::vector<std::string> app_modules_list_{};
|
|
||||||
|
|
||||||
Context() {}
|
Context() {}
|
||||||
|
|
||||||
|
|
@ -114,14 +97,6 @@ namespace lspd {
|
||||||
static jclass FindClassFromLoader(JNIEnv *env, jobject class_loader,
|
static jclass FindClassFromLoader(JNIEnv *env, jobject class_loader,
|
||||||
std::string_view class_name);
|
std::string_view class_name);
|
||||||
|
|
||||||
static bool
|
|
||||||
ShouldSkipInject(const std::string &package_name, uid_t user, uid_t uid, bool res,
|
|
||||||
const std::function<bool()> &empty_list,
|
|
||||||
bool is_child_zygote);
|
|
||||||
|
|
||||||
static std::tuple<bool, uid_t, std::string>
|
|
||||||
GetAppInfoFromDir(JNIEnv *env, jstring dir, jstring nice_name);
|
|
||||||
|
|
||||||
friend std::unique_ptr<Context> std::make_unique<Context>();
|
friend std::unique_ptr<Context> std::make_unique<Context>();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,13 +74,7 @@ namespace lspd {
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getModulesList) {
|
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getModulesList) {
|
||||||
auto module_list = Context::GetInstance()->GetAppModulesList();
|
return nullptr;
|
||||||
std::ostringstream join;
|
|
||||||
std::copy(module_list.begin(), module_list.end(),
|
|
||||||
std::ostream_iterator<std::string>(join, "\n"));
|
|
||||||
const auto &list = join.str();
|
|
||||||
LOGD("module list: %s", list.c_str());
|
|
||||||
return env->NewStringUTF(list.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isPermissive) {
|
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isPermissive) {
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,6 @@
|
||||||
#include "config_manager.h"
|
#include "config_manager.h"
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-value"
|
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
static void onModuleLoaded() {
|
static void onModuleLoaded() {
|
||||||
LOGI("onModuleLoaded: welcome to LSPosed!");
|
LOGI("onModuleLoaded: welcome to LSPosed!");
|
||||||
|
|
@ -63,7 +60,7 @@ namespace lspd {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
static void nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||||
Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, res);
|
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid,
|
static void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid,
|
||||||
|
|
@ -77,8 +74,8 @@ namespace lspd {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
|
static void nativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) {
|
||||||
Context::GetInstance()->OnNativeForkSystemServerPost(env, clazz, res);
|
Context::GetInstance()->OnNativeForkSystemServerPost(env, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* method added in Android Q */
|
/* method added in Android Q */
|
||||||
|
|
@ -97,13 +94,12 @@ namespace lspd {
|
||||||
*app_data_dir);
|
*app_data_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void specializeAppProcessPost(JNIEnv *env, jclass clazz) {
|
static void specializeAppProcessPost(JNIEnv *env, [[maybe_unused]] jclass clazz) {
|
||||||
Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, 0);
|
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int riru_api_version;
|
int riru_api_version;
|
||||||
RiruApiV10 *riru_api_v10;
|
|
||||||
|
|
||||||
RIRU_EXPORT void *init(void *arg) {
|
RIRU_EXPORT void *init(void *arg) {
|
||||||
static int step = 0;
|
static int step = 0;
|
||||||
|
|
@ -122,8 +118,6 @@ RIRU_EXPORT void *init(void *arg) {
|
||||||
case 10:
|
case 10:
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case 9: {
|
case 9: {
|
||||||
riru_api_v10 = (RiruApiV10 *) arg;
|
|
||||||
|
|
||||||
auto module = (RiruModuleInfoV10 *) malloc(sizeof(RiruModuleInfoV10));
|
auto module = (RiruModuleInfoV10 *) malloc(sizeof(RiruModuleInfoV10));
|
||||||
memset(module, 0, sizeof(RiruModuleInfoV10));
|
memset(module, 0, sizeof(RiruModuleInfoV10));
|
||||||
_module = module;
|
_module = module;
|
||||||
|
|
@ -156,5 +150,3 @@ RIRU_EXPORT void *init(void *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
|
|
@ -3,27 +3,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <nativehelper/scoped_local_ref.h>
|
#include <nativehelper/scoped_local_ref.h>
|
||||||
#include <base/object.h>
|
|
||||||
#include <dobby.h>
|
#include <dobby.h>
|
||||||
|
#include "base/object.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "JNIHelper.h"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
|
jboolean Service::exec_transact_replace(jboolean *res, JNIEnv *env, [[maybe_unused]] jobject obj, va_list args) {
|
||||||
namespace {
|
|
||||||
constexpr uint32_t BRIDGE_TRANSACTION_CODE = 1598837584;
|
|
||||||
|
|
||||||
JNINativeInterface native_interface_replace{};
|
|
||||||
jmethodID exec_transact_backup_methodID = nullptr;
|
|
||||||
|
|
||||||
jboolean (*call_boolean_method_va_backup)(JNIEnv *env, jobject obj, jmethodID methodId,
|
|
||||||
va_list args) = nullptr;
|
|
||||||
|
|
||||||
jclass bridge_service_class = nullptr;
|
|
||||||
jmethodID exec_transact_replace_methodID = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool exec_transact_replace(jboolean *res, JNIEnv *env, jobject obj, va_list args) {
|
|
||||||
jint code;
|
jint code;
|
||||||
|
|
||||||
va_list copy;
|
va_list copy;
|
||||||
|
|
@ -32,8 +19,8 @@ namespace lspd {
|
||||||
va_end(copy);
|
va_end(copy);
|
||||||
|
|
||||||
if (UNLIKELY(code == BRIDGE_TRANSACTION_CODE)) {
|
if (UNLIKELY(code == BRIDGE_TRANSACTION_CODE)) {
|
||||||
*res = env->CallStaticBooleanMethodV(bridge_service_class,
|
*res = env->CallStaticBooleanMethodV(instance()->bridge_service_class_,
|
||||||
exec_transact_replace_methodID,
|
instance()->exec_transact_replace_methodID_,
|
||||||
args);
|
args);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -41,50 +28,139 @@ namespace lspd {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jboolean
|
jboolean
|
||||||
call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) {
|
Service::call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId,
|
||||||
if (UNLIKELY(methodId == exec_transact_backup_methodID)) {
|
va_list args) {
|
||||||
|
if (UNLIKELY(methodId == instance()->exec_transact_backup_methodID_)) {
|
||||||
jboolean res = false;
|
jboolean res = false;
|
||||||
if (LIKELY(exec_transact_replace(&res, env, obj, args))) return res;
|
if (LIKELY(exec_transact_replace(&res, env, obj, args))) return res;
|
||||||
// else fallback to backup
|
// else fallback to backup
|
||||||
}
|
}
|
||||||
return call_boolean_method_va_backup(env, obj, methodId, args);
|
return instance()->call_boolean_method_va_backup_(env, obj, methodId, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitService(const Context &context, JNIEnv *env) {
|
void Service::InitService(JNIEnv *env) {
|
||||||
bridge_service_class = context.FindClassFromCurrentLoader(env, kBridgeServiceClassName);
|
if (LIKELY(initialized_)) return;
|
||||||
if (!bridge_service_class) {
|
initialized_ = true;
|
||||||
|
|
||||||
|
// ServiceManager
|
||||||
|
serviceManagerClass_ = env->FindClass("android/os/ServiceManager");
|
||||||
|
if (serviceManagerClass_) {
|
||||||
|
serviceManagerClass_ = (jclass) env->NewGlobalRef(serviceManagerClass_);
|
||||||
|
} else {
|
||||||
|
env->ExceptionClear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getServiceMethod_ = env->GetStaticMethodID(serviceManagerClass_, "getService",
|
||||||
|
"(Ljava/lang/String;)Landroid/os/IBinder;");
|
||||||
|
if (!getServiceMethod_) {
|
||||||
|
env->ExceptionClear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IBinder
|
||||||
|
jclass iBinderClass = env->FindClass("android/os/IBinder");
|
||||||
|
transactMethod_ = env->GetMethodID(iBinderClass, "transact",
|
||||||
|
"(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z");
|
||||||
|
|
||||||
|
// Parcel
|
||||||
|
parcelClass_ = env->FindClass("android/os/Parcel");
|
||||||
|
if (parcelClass_) parcelClass_ = (jclass) env->NewGlobalRef(parcelClass_);
|
||||||
|
obtainMethod_ = env->GetStaticMethodID(parcelClass_, "obtain", "()Landroid/os/Parcel;");
|
||||||
|
recycleMethod_ = env->GetMethodID(parcelClass_, "recycle", "()V");
|
||||||
|
writeInterfaceTokenMethod_ = env->GetMethodID(parcelClass_, "writeInterfaceToken",
|
||||||
|
"(Ljava/lang/String;)V");
|
||||||
|
writeIntMethod_ = env->GetMethodID(parcelClass_, "writeInt", "(I)V");
|
||||||
|
writeStringMethod_ = env->GetMethodID(parcelClass_, "writeString", "(Ljava/lang/String;)V");
|
||||||
|
readExceptionMethod_ = env->GetMethodID(parcelClass_, "readException", "()V");
|
||||||
|
readStrongBinderMethod_ = env->GetMethodID(parcelClass_, "readStrongBinder",
|
||||||
|
"()Landroid/os/IBinder;");
|
||||||
|
createStringArray_ = env->GetMethodID(parcelClass_, "createStringArray",
|
||||||
|
"()[Ljava/lang/String;");
|
||||||
|
|
||||||
|
deadObjectExceptionClass_ = env->FindClass("android/os/DeadObjectException");
|
||||||
|
if (deadObjectExceptionClass_)
|
||||||
|
deadObjectExceptionClass_ = (jclass) env->NewGlobalRef(deadObjectExceptionClass_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::HookBridge(const Context &context, JNIEnv *env) {
|
||||||
|
static bool hooked = false;
|
||||||
|
// This should only be ran once, so unlikely
|
||||||
|
if (UNLIKELY(hooked)) return;
|
||||||
|
hooked = true;
|
||||||
|
bridge_service_class_ = context.FindClassFromCurrentLoader(env, kBridgeServiceClassName);
|
||||||
|
if (!bridge_service_class_) {
|
||||||
LOGE("server class not found");
|
LOGE("server class not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bridge_service_class = (jclass) env->NewGlobalRef(bridge_service_class);
|
bridge_service_class_ = (jclass) env->NewGlobalRef(bridge_service_class_);
|
||||||
exec_transact_replace_methodID = env->GetStaticMethodID(bridge_service_class,
|
exec_transact_replace_methodID_ = env->GetStaticMethodID(bridge_service_class_,
|
||||||
"execTransact",
|
"execTransact",
|
||||||
"(IJJI)Z");
|
"(IJJI)Z");
|
||||||
if (!exec_transact_replace_methodID) {
|
if (!exec_transact_replace_methodID_) {
|
||||||
LOGE("execTransact class not found");
|
LOGE("execTransact class not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedLocalRef<jclass> binderClass(env, env->FindClass("android/os/Binder"));
|
ScopedLocalRef<jclass> binderClass(env, env->FindClass("android/os/Binder"));
|
||||||
exec_transact_backup_methodID = env->GetMethodID(binderClass.get(), "execTransact",
|
exec_transact_backup_methodID_ = env->GetMethodID(binderClass.get(), "execTransact",
|
||||||
"(IJJI)Z");
|
"(IJJI)Z");
|
||||||
auto set_table_override = reinterpret_cast<void (*)(
|
auto set_table_override = reinterpret_cast<void (*)(
|
||||||
JNINativeInterface *)>(DobbySymbolResolver(nullptr,
|
JNINativeInterface *)>(DobbySymbolResolver(nullptr,
|
||||||
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface"));
|
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface"));
|
||||||
if (!set_table_override) {
|
if (!set_table_override) {
|
||||||
LOGE("set table override not found");
|
LOGE("set table override not found");
|
||||||
}
|
}
|
||||||
memcpy(&native_interface_replace, env->functions, sizeof(JNINativeInterface));
|
memcpy(&native_interface_replace_, env->functions, sizeof(JNINativeInterface));
|
||||||
|
|
||||||
call_boolean_method_va_backup = env->functions->CallBooleanMethodV;
|
call_boolean_method_va_backup_ = env->functions->CallBooleanMethodV;
|
||||||
native_interface_replace.CallBooleanMethodV = &call_boolean_method_va_replace;
|
native_interface_replace_.CallBooleanMethodV = &call_boolean_method_va_replace;
|
||||||
|
|
||||||
if (set_table_override != nullptr) {
|
if (set_table_override != nullptr) {
|
||||||
set_table_override(&native_interface_replace);
|
set_table_override(&native_interface_replace_);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("Done InitService");
|
LOGD("Done InitService");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobject Service::RequestBinder(JNIEnv *env) {
|
||||||
|
if (UNLIKELY(!initialized_)) {
|
||||||
|
LOGE("Service not initialized");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto bridgeServiceName = env->NewStringUTF(BRIDGE_SERVICE_NAME.data());
|
||||||
|
auto bridgeService = JNI_CallStaticObjectMethod(env, serviceManagerClass_,
|
||||||
|
getServiceMethod_, bridgeServiceName);
|
||||||
|
if (!bridgeService) {
|
||||||
|
LOGD("can't get %s", BRIDGE_SERVICE_NAME.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = JNI_CallStaticObjectMethod(env, parcelClass_, obtainMethod_);
|
||||||
|
auto reply = JNI_CallStaticObjectMethod(env, parcelClass_, obtainMethod_);
|
||||||
|
|
||||||
|
auto descriptor = env->NewStringUTF(BRIDGE_SERVICE_DESCRIPTOR.data());
|
||||||
|
JNI_CallVoidMethod(env, data, writeInterfaceTokenMethod_, descriptor);
|
||||||
|
JNI_CallVoidMethod(env, data, writeIntMethod_, BRIDGE_ACTION_GET_BINDER);
|
||||||
|
|
||||||
|
auto res = JNI_CallBooleanMethod(env, bridgeService, transactMethod_,
|
||||||
|
BRIDGE_TRANSACTION_CODE,
|
||||||
|
data,
|
||||||
|
reply, 0);
|
||||||
|
|
||||||
|
jobject service = nullptr;
|
||||||
|
if (res) {
|
||||||
|
JNI_CallVoidMethod(env, reply, readExceptionMethod_);
|
||||||
|
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
||||||
|
} else {
|
||||||
|
LOGD("no reply");
|
||||||
|
}
|
||||||
|
|
||||||
|
JNI_CallVoidMethod(env, data, recycleMethod_);
|
||||||
|
JNI_CallObjectMethod(env, reply, recycleMethod_);
|
||||||
|
|
||||||
|
return service;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,72 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
|
using namespace std::literals::string_view_literals;
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
void InitService(const Context & context, JNIEnv *env);
|
class Service {
|
||||||
|
constexpr static jint BRIDGE_TRANSACTION_CODE = 1598837584;
|
||||||
|
constexpr static auto BRIDGE_SERVICE_DESCRIPTOR = "android.app.IActivityManager"sv;
|
||||||
|
constexpr static auto BRIDGE_SERVICE_NAME = "activity"sv;
|
||||||
|
constexpr static jint BRIDGE_ACTION_GET_BINDER = 2;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline static Service* instance() {
|
||||||
|
return instance_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static std::unique_ptr<Service> ReleaseInstance() {
|
||||||
|
return std::move(instance_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitService(JNIEnv *env);
|
||||||
|
|
||||||
|
void HookBridge(const Context& context, JNIEnv *env);
|
||||||
|
|
||||||
|
jobject RequestBinder(JNIEnv *env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline static std::unique_ptr<Service> instance_ = std::make_unique<Service>();
|
||||||
|
bool initialized_ = false;
|
||||||
|
|
||||||
|
Service() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static jboolean
|
||||||
|
call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args);
|
||||||
|
|
||||||
|
static jboolean exec_transact_replace(jboolean *res, JNIEnv *env, jobject obj, va_list args);
|
||||||
|
|
||||||
|
JNINativeInterface native_interface_replace_{};
|
||||||
|
jmethodID exec_transact_backup_methodID_ = nullptr;
|
||||||
|
|
||||||
|
jboolean (*call_boolean_method_va_backup_)(JNIEnv *env, jobject obj, jmethodID methodId,
|
||||||
|
va_list args) = nullptr;
|
||||||
|
|
||||||
|
jclass bridge_service_class_ = nullptr;
|
||||||
|
jmethodID exec_transact_replace_methodID_ = nullptr;
|
||||||
|
|
||||||
|
jclass serviceManagerClass_ = nullptr;
|
||||||
|
jmethodID getServiceMethod_ = nullptr;
|
||||||
|
|
||||||
|
jmethodID transactMethod_ = nullptr;
|
||||||
|
|
||||||
|
jclass parcelClass_ = nullptr;
|
||||||
|
jmethodID obtainMethod_ = nullptr;
|
||||||
|
jmethodID recycleMethod_ = nullptr;
|
||||||
|
jmethodID writeInterfaceTokenMethod_ = nullptr;
|
||||||
|
jmethodID writeIntMethod_ = nullptr;
|
||||||
|
jmethodID writeStringMethod_ = nullptr;
|
||||||
|
jmethodID readExceptionMethod_ = nullptr;
|
||||||
|
jmethodID readStrongBinderMethod_ = nullptr;
|
||||||
|
jmethodID createStringArray_ = nullptr;
|
||||||
|
|
||||||
|
jclass deadObjectExceptionClass_ = nullptr;
|
||||||
|
|
||||||
|
friend std::unique_ptr<Service> std::make_unique<Service>();
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,14 @@ package io.github.lsposed.lspd.core;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.ddm.DdmHandleAppName;
|
import android.ddm.DdmHandleAppName;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepAll;
|
import io.github.lsposed.common.KeepAll;
|
||||||
|
import io.github.lsposed.lspd.service.ILSPApplicationService;
|
||||||
import io.github.lsposed.lspd.service.ServiceManager;
|
import io.github.lsposed.lspd.service.ServiceManager;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
|
|
@ -36,43 +40,41 @@ import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public class Main implements KeepAll {
|
public class Main implements KeepAll {
|
||||||
private static final AtomicReference<EdxpImpl> lspdImplRef = new AtomicReference<>(null);
|
private static final AtomicReference<EdxpImpl> lspdImplRef = new AtomicReference<>(null);
|
||||||
|
private static final Binder heartBeatBinder = new Binder();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
|
||||||
// entry points
|
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
final int variant;
|
||||||
|
try {
|
||||||
public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags,
|
service.registerHeartBeat(heartBeatBinder);
|
||||||
int[][] rlimits, int mountExternal, String seInfo,
|
variant = service.getVariant();
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
} catch (RemoteException e) {
|
||||||
boolean startChildZygote, String instructionSet,
|
Utils.logW("Register fail", e);
|
||||||
String appDataDir) {
|
return;
|
||||||
// won't be loaded
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void forkAndSpecializePost(int pid, String appDataDir, String niceName, int variant) {
|
|
||||||
EdxpImpl lspd = getEdxpImpl(variant);
|
EdxpImpl lspd = getEdxpImpl(variant);
|
||||||
if (lspd == null || !lspd.isInitialized()) {
|
if (lspd == null || !lspd.isInitialized()) {
|
||||||
Utils.logE("Not started up");
|
Utils.logE("Not started up");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pid == 0) {
|
lspd.getNormalProxy().forkAndSpecializePost(appDataDir, niceName);
|
||||||
lspd.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName);
|
}
|
||||||
|
|
||||||
|
public static void forkSystemServerPost(IBinder binder) {
|
||||||
|
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
||||||
|
final int variant;
|
||||||
|
try {
|
||||||
|
service.registerHeartBeat(heartBeatBinder);
|
||||||
|
variant = service.getVariant();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Utils.logW("Register fail", e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
|
||||||
long permittedCapabilities, long effectiveCapabilities) {
|
|
||||||
// Won't load
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forkSystemServerPost(int pid, int variant) {
|
|
||||||
EdxpImpl lspd = getEdxpImpl(variant);
|
EdxpImpl lspd = getEdxpImpl(variant);
|
||||||
if (lspd == null || !lspd.isInitialized()) {
|
if (lspd == null || !lspd.isInitialized()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pid == 0) {
|
lspd.getNormalProxy().forkSystemServerPost();
|
||||||
lspd.getNormalProxy().forkSystemServerPost(pid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized boolean setEdxpImpl(EdxpImpl lspd) {
|
public static synchronized boolean setEdxpImpl(EdxpImpl lspd) {
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,6 @@ public interface Proxy extends KeepAll {
|
||||||
|
|
||||||
boolean init();
|
boolean init();
|
||||||
|
|
||||||
void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags,
|
void forkAndSpecializePost(String appDataDir, String niceName);
|
||||||
int[][] rlimits, int mountExternal, String seInfo,
|
void forkSystemServerPost();
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
|
||||||
boolean startChildZygote, String instructionSet,
|
|
||||||
String appDataDir);
|
|
||||||
|
|
||||||
void forkAndSpecializePost(int pid, String appDataDir, String niceName);
|
|
||||||
|
|
||||||
void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
|
||||||
long permittedCapabilities, long effectiveCapabilities);
|
|
||||||
|
|
||||||
void forkSystemServerPost(int pid);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,28 +35,17 @@ public class NormalProxy extends BaseProxy {
|
||||||
super(router);
|
super(router);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags,
|
public void forkAndSpecializePost(String appDataDir, String niceName) {
|
||||||
int[][] rlimits, int mountExternal, String seInfo,
|
forkPostCommon(false, appDataDir, niceName);
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
|
||||||
boolean startChildZygote, String instructionSet,
|
|
||||||
String appDataDir) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
|
public void forkSystemServerPost() {
|
||||||
forkPostCommon(pid, false, appDataDir, niceName);
|
forkPostCommon(true,
|
||||||
}
|
|
||||||
|
|
||||||
public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
|
||||||
long permittedCapabilities, long effectiveCapabilities) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void forkSystemServerPost(int pid) {
|
|
||||||
forkPostCommon(pid, true,
|
|
||||||
getDataPathPrefix() + "android", "system_server");
|
getDataPathPrefix() + "android", "system_server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void forkPostCommon(int pid, boolean isSystem, String appDataDir, String niceName) {
|
private void forkPostCommon(boolean isSystem, String appDataDir, String niceName) {
|
||||||
SELinuxHelper.initOnce();
|
SELinuxHelper.initOnce();
|
||||||
mRouter.initResourcesHook();
|
mRouter.initResourcesHook();
|
||||||
mRouter.prepare(isSystem);
|
mRouter.prepare(isSystem);
|
||||||
|
|
|
||||||
|
|
@ -29,23 +29,32 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getVariant() throws RemoteException {
|
||||||
|
ensureRegistered();
|
||||||
|
return ConfigManager.getInstance().variant();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check if module
|
// TODO: check if module
|
||||||
@Override
|
@Override
|
||||||
public IBinder requestModuleBinder() {
|
public IBinder requestModuleBinder() throws RemoteException {
|
||||||
if (!hasRegister(Binder.getCallingUid(), Binder.getCallingPid()))
|
ensureRegistered();
|
||||||
return null;
|
|
||||||
return ServiceManager.getModuleService();
|
return ServiceManager.getModuleService();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if manager
|
// TODO: check if manager
|
||||||
@Override
|
@Override
|
||||||
public IBinder requestManagerBinder() {
|
public IBinder requestManagerBinder() throws RemoteException {
|
||||||
if (!hasRegister(Binder.getCallingUid(), Binder.getCallingPid()))
|
ensureRegistered();
|
||||||
return null;
|
|
||||||
return ServiceManager.getManagerService();
|
return ServiceManager.getManagerService();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasRegister(int uid, int pid) {
|
public boolean hasRegister(int uid, int pid) {
|
||||||
return cache.contains(new Pair<>(uid, pid));
|
return cache.contains(new Pair<>(uid, pid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureRegistered() throws RemoteException {
|
||||||
|
if (!hasRegister(Binder.getCallingUid(), Binder.getCallingPid()))
|
||||||
|
throw new RemoteException("Not registered");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue