Cleanup zygisk headers

This commit is contained in:
topjohnwu 2022-08-30 01:40:14 -07:00
parent 38325e708e
commit 14b830027b
5 changed files with 161 additions and 136 deletions

View File

@ -220,7 +220,7 @@ struct Api {
bool pltHookCommit(); bool pltHookCommit();
private: private:
internal::api_table *impl; internal::api_table *tbl;
template <class T> friend void internal::entry_impl(internal::api_table *, JNIEnv *); template <class T> friend void internal::entry_impl(internal::api_table *, JNIEnv *);
}; };
@ -244,46 +244,43 @@ void zygisk_module_entry(zygisk::internal::api_table *table, JNIEnv *env) { \
#define REGISTER_ZYGISK_COMPANION(func) \ #define REGISTER_ZYGISK_COMPANION(func) \
void zygisk_companion_entry(int client) { func(client); } void zygisk_companion_entry(int client) { func(client); }
/************************************************************************************ /*********************************************************
* All the code after this point is internal code used to interface with Zygisk * The following is internal ABI implementation detail.
* and guarantee ABI stability. You do not have to understand what it is doing. * You do not have to understand what it is doing.
************************************************************************************/ *********************************************************/
namespace internal { namespace internal {
struct module_abi { struct module_abi {
long api_version; long api_version;
ModuleBase *_this; ModuleBase *impl;
void (*preAppSpecialize)(ModuleBase *, AppSpecializeArgs *); void (*preAppSpecialize)(ModuleBase *, AppSpecializeArgs *);
void (*postAppSpecialize)(ModuleBase *, const AppSpecializeArgs *); void (*postAppSpecialize)(ModuleBase *, const AppSpecializeArgs *);
void (*preServerSpecialize)(ModuleBase *, ServerSpecializeArgs *); void (*preServerSpecialize)(ModuleBase *, ServerSpecializeArgs *);
void (*postServerSpecialize)(ModuleBase *, const ServerSpecializeArgs *); void (*postServerSpecialize)(ModuleBase *, const ServerSpecializeArgs *);
module_abi(ModuleBase *module) : api_version(ZYGISK_API_VERSION), _this(module) { module_abi(ModuleBase *module) : api_version(ZYGISK_API_VERSION), impl(module) {
preAppSpecialize = [](auto self, auto args) { self->preAppSpecialize(args); }; preAppSpecialize = [](auto m, auto args) { m->preAppSpecialize(args); };
postAppSpecialize = [](auto self, auto args) { self->postAppSpecialize(args); }; postAppSpecialize = [](auto m, auto args) { m->postAppSpecialize(args); };
preServerSpecialize = [](auto self, auto args) { self->preServerSpecialize(args); }; preServerSpecialize = [](auto m, auto args) { m->preServerSpecialize(args); };
postServerSpecialize = [](auto self, auto args) { self->postServerSpecialize(args); }; postServerSpecialize = [](auto m, auto args) { m->postServerSpecialize(args); };
} }
}; };
struct api_table { struct api_table {
// These first 2 entries are permanent, shall never change // Base
void *_this; void *impl;
bool (*registerModule)(api_table *, module_abi *); bool (*registerModule)(api_table *, module_abi *);
// Utility functions
void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int); void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int);
void (*pltHookRegister)(const char *, const char *, void *, void **); void (*pltHookRegister)(const char *, const char *, void *, void **);
void (*pltHookExclude)(const char *, const char *); void (*pltHookExclude)(const char *, const char *);
bool (*pltHookCommit)(); bool (*pltHookCommit)();
int (*connectCompanion)(void * /* impl */);
// Zygisk functions void (*setOption)(void * /* impl */, Option);
int (*connectCompanion)(void * /* _this */); int (*getModuleDir)(void * /* impl */);
void (*setOption)(void * /* _this */, Option); uint32_t (*getFlags)(void * /* impl */);
int (*getModuleDir)(void * /* _this */);
uint32_t (*getFlags)(void * /* _this */);
}; };
template <class T> template <class T>
@ -292,35 +289,35 @@ void entry_impl(api_table *table, JNIEnv *env) {
if (!table->registerModule(table, new module_abi(module))) if (!table->registerModule(table, new module_abi(module)))
return; return;
auto api = new Api(); auto api = new Api();
api->impl = table; api->tbl = table;
module->onLoad(api, env); module->onLoad(api, env);
} }
} // namespace internal } // namespace internal
inline int Api::connectCompanion() { inline int Api::connectCompanion() {
return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1; return tbl->connectCompanion ? tbl->connectCompanion(tbl->impl) : -1;
} }
inline int Api::getModuleDir() { inline int Api::getModuleDir() {
return impl->getModuleDir ? impl->getModuleDir(impl->_this) : -1; return tbl->getModuleDir ? tbl->getModuleDir(tbl->impl) : -1;
} }
inline void Api::setOption(Option opt) { inline void Api::setOption(Option opt) {
if (impl->setOption) impl->setOption(impl->_this, opt); if (tbl->setOption) tbl->setOption(tbl->impl, opt);
} }
inline uint32_t Api::getFlags() { inline uint32_t Api::getFlags() {
return impl->getFlags ? impl->getFlags(impl->_this) : 0; return tbl->getFlags ? tbl->getFlags(tbl->impl) : 0;
} }
inline void Api::hookJniNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods) { inline void Api::hookJniNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods) {
if (impl->hookJniNativeMethods) impl->hookJniNativeMethods(env, className, methods, numMethods); if (tbl->hookJniNativeMethods) tbl->hookJniNativeMethods(env, className, methods, numMethods);
} }
inline void Api::pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc) { inline void Api::pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc) {
if (impl->pltHookRegister) impl->pltHookRegister(regex, symbol, newFunc, oldFunc); if (tbl->pltHookRegister) tbl->pltHookRegister(regex, symbol, newFunc, oldFunc);
} }
inline void Api::pltHookExclude(const char *regex, const char *symbol) { inline void Api::pltHookExclude(const char *regex, const char *symbol) {
if (impl->pltHookExclude) impl->pltHookExclude(regex, symbol); if (tbl->pltHookExclude) tbl->pltHookExclude(regex, symbol);
} }
inline bool Api::pltHookCommit() { inline bool Api::pltHookCommit() {
return impl->pltHookCommit != nullptr && impl->pltHookCommit(); return tbl->pltHookCommit != nullptr && tbl->pltHookCommit();
} }
} // namespace zygisk } // namespace zygisk

View File

@ -97,7 +97,7 @@ class ForkAndSpec(JNIHook):
decl += ind(1) + f'args.{a.name} = &{a.name};' decl += ind(1) + f'args.{a.name} = &{a.name};'
decl += ind(1) + 'HookContext ctx;' decl += ind(1) + 'HookContext ctx;'
decl += ind(1) + 'ctx.env = env;' decl += ind(1) + 'ctx.env = env;'
decl += ind(1) + 'ctx.raw_args = &args;' decl += ind(1) + 'ctx.args = { &args };'
decl += ind(1) + f'ctx.{self.base_name()}_pre();' decl += ind(1) + f'ctx.{self.base_name()}_pre();'
decl += ind(1) + self.orig_method() + '(' decl += ind(1) + self.orig_method() + '('
decl += ind(2) + f'env, clazz, {self.name_list()}' decl += ind(2) + f'env, clazz, {self.name_list()}'

View File

@ -43,10 +43,10 @@ void name##_post();
struct HookContext { struct HookContext {
JNIEnv *env; JNIEnv *env;
union { union {
AppSpecializeArgs_v3 *args; void *ptr;
ServerSpecializeArgs_v1 *server_args; AppSpecializeArgs_v3 *app;
void *raw_args; ServerSpecializeArgs_v1 *server;
}; } args;
const char *process; const char *process;
vector<ZygiskModule> modules; vector<ZygiskModule> modules;
bitset<FLAG_MAX> state; bitset<FLAG_MAX> state;
@ -54,7 +54,7 @@ struct HookContext {
int pid; int pid;
uint32_t flags; uint32_t flags;
HookContext() : pid(-1), flags(0) {} HookContext() : env(nullptr), args{nullptr}, process(nullptr), pid(-1), flags(0) {}
static void close_fds(); static void close_fds();
void unload_zygisk(); void unload_zygisk();
@ -280,39 +280,49 @@ void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods
} }
ZygiskModule::ZygiskModule(int id, void *handle, void *entry) ZygiskModule::ZygiskModule(int id, void *handle, void *entry)
: raw_entry(entry), api(this), id(id), handle(handle) {} : id(id), handle(handle), entry{entry}, api{}, mod{nullptr} {
// Make sure all pointers are null
memset(&api, 0, sizeof(api));
api.base.impl = this;
api.base.registerModule = &ZygiskModule::RegisterModule;
}
ApiTable::ApiTable(ZygiskModule *m) bool ZygiskModule::RegisterModule(api_abi_base *api, long *module) {
: module(m), registerModule(&ZygiskModule::RegisterModule) {} long api_version = *module;
bool ZygiskModule::RegisterModule(ApiTable *table, long *module) {
long ver = *module;
// Unsupported version // Unsupported version
if (ver > ZYGISK_API_VERSION) if (api_version > ZYGISK_API_VERSION)
return false; return false;
// Set the actual module_abi* // Set the actual module_abi*
table->module->ver = module; api->impl->mod = { module };
// Fill in API accordingly with module API version // Fill in API accordingly with module API version
switch (ver) { switch (api_version) {
case 3: case 3:
case 2: case 2: {
table->v2.getModuleDir = [](ZygiskModule *m) { return m->getModuleDir(); }; auto v2 = static_cast<api_abi_v2 *>(api);
table->v2.getFlags = [](auto) { return ZygiskModule::getFlags(); }; v2->getModuleDir = [](ZygiskModule *m) { return m->getModuleDir(); };
v2->getFlags = [](auto) { return ZygiskModule::getFlags(); };
}
// fallthrough // fallthrough
case 1: case 1: {
table->v1.hookJniNativeMethods = &hookJniNativeMethods; auto v1 = static_cast<api_abi_v1 *>(api);
table->v1.pltHookRegister = [](const char *p, const char *s, void *n, void **o) { v1->hookJniNativeMethods = &hookJniNativeMethods;
v1->pltHookRegister = [](const char *p, const char *s, void *n, void **o) {
xhook_register(p, s, n, o); xhook_register(p, s, n, o);
}; };
table->v1.pltHookExclude = [](const char *p, const char *s) { v1->pltHookExclude = [](const char *p, const char *s) {
xhook_ignore(p, s); xhook_ignore(p, s);
}; };
table->v1.pltHookCommit = []{ bool r = xhook_refresh(0) == 0; xhook_clear(); return r; }; v1->pltHookCommit = [] {
table->v1.connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); }; bool r = xhook_refresh(0) == 0;
table->v1.setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); }; xhook_clear();
return r;
};
v1->connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); };
v1->setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); };
break; break;
}
default: default:
// Unknown version number // Unknown version number
return false; return false;
@ -395,17 +405,17 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
} }
for (auto &m : modules) { for (auto &m : modules) {
m.entry(&m.api, env); m.onLoad(env);
if (state[APP_SPECIALIZE]) { if (state[APP_SPECIALIZE]) {
m.preAppSpecialize(args); m.preAppSpecialize(args.app);
} else if (state[SERVER_SPECIALIZE]) { } else if (state[SERVER_SPECIALIZE]) {
m.preServerSpecialize(server_args); m.preServerSpecialize(args.server);
} }
} }
// Add all ignored fd onto whitelist // Add all ignored fd onto whitelist
if (state[APP_SPECIALIZE] && args->fds_to_ignore) { if (state[APP_SPECIALIZE] && args.app->fds_to_ignore) {
if (jintArray fdsToIgnore = *args->fds_to_ignore) { if (jintArray fdsToIgnore = *args.app->fds_to_ignore) {
int len = env->GetArrayLength(fdsToIgnore); int len = env->GetArrayLength(fdsToIgnore);
int *arr = env->GetIntArrayElements(fdsToIgnore, nullptr); int *arr = env->GetIntArrayElements(fdsToIgnore, nullptr);
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
@ -431,11 +441,11 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
void HookContext::run_modules_post() { void HookContext::run_modules_post() {
for (const auto &m : modules) { for (const auto &m : modules) {
if (state[APP_SPECIALIZE]) { if (state[APP_SPECIALIZE]) {
m.postAppSpecialize(args); m.postAppSpecialize(args.app);
} else if (state[SERVER_SPECIALIZE]) { } else if (state[SERVER_SPECIALIZE]) {
m.postServerSpecialize(server_args); m.postServerSpecialize(args.server);
} }
m.doUnload(); m.tryUnload();
} }
} }
@ -452,7 +462,7 @@ void HookContext::unload_zygisk() {
// Strip out all API function pointers // Strip out all API function pointers
for (auto &m : modules) { for (auto &m : modules) {
memset(&m.api, 0, sizeof(m.api)); m.clearApi();
} }
new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle); new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle);
@ -464,7 +474,7 @@ void HookContext::unload_zygisk() {
void HookContext::nativeSpecializeAppProcess_pre() { void HookContext::nativeSpecializeAppProcess_pre() {
g_ctx = this; g_ctx = this;
state[APP_SPECIALIZE] = true; state[APP_SPECIALIZE] = true;
process = env->GetStringUTFChars(args->nice_name, nullptr); process = env->GetStringUTFChars(args.app->nice_name, nullptr);
if (state[FORK_AND_SPECIALIZE]) { if (state[FORK_AND_SPECIALIZE]) {
ZLOGV("pre forkAndSpecialize [%s]\n", process); ZLOGV("pre forkAndSpecialize [%s]\n", process);
} else { } else {
@ -472,7 +482,7 @@ void HookContext::nativeSpecializeAppProcess_pre() {
} }
vector<int> module_fds; vector<int> module_fds;
int fd = remote_get_info(args->uid, process, &flags, module_fds); int fd = remote_get_info(args.app->uid, process, &flags, module_fds);
if ((flags & UNMOUNT_MASK) == UNMOUNT_MASK) { if ((flags & UNMOUNT_MASK) == UNMOUNT_MASK) {
ZLOGI("[%s] is on the denylist\n", process); ZLOGI("[%s] is on the denylist\n", process);
state[DO_UNMOUNT] = true; state[DO_UNMOUNT] = true;
@ -492,7 +502,7 @@ void HookContext::nativeSpecializeAppProcess_post() {
ZLOGV("post specialize [%s]\n", process); ZLOGV("post specialize [%s]\n", process);
} }
env->ReleaseStringUTFChars(args->nice_name, process); env->ReleaseStringUTFChars(args.app->nice_name, process);
run_modules_post(); run_modules_post();
if (flags & PROCESS_IS_MAGISK_APP) { if (flags & PROCESS_IS_MAGISK_APP) {
setenv("ZYGISK_ENABLED", "1", 1); setenv("ZYGISK_ENABLED", "1", 1);

View File

@ -7,7 +7,7 @@ jint nativeForkAndSpecialize_l(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir); AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_l)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_l)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir
@ -20,7 +20,7 @@ jint nativeForkAndSpecialize_o(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.fds_to_ignore = &fds_to_ignore; args.fds_to_ignore = &fds_to_ignore;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_o)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_o)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
@ -34,7 +34,7 @@ jint nativeForkAndSpecialize_p(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.is_child_zygote = &is_child_zygote; args.is_child_zygote = &is_child_zygote;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_p)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_p)>(nativeForkAndSpecialize_orig)(
env, clazz, 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 env, clazz, 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
@ -49,7 +49,7 @@ jint nativeForkAndSpecialize_q_alt(JNIEnv *env, jclass clazz, jint uid, jint gid
args.is_top_app = &is_top_app; args.is_top_app = &is_top_app;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_q_alt)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_q_alt)>(nativeForkAndSpecialize_orig)(
env, clazz, 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, is_top_app env, clazz, 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, is_top_app
@ -68,7 +68,7 @@ jint nativeForkAndSpecialize_r(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.mount_storage_dirs = &mount_storage_dirs; args.mount_storage_dirs = &mount_storage_dirs;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_r)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_r)>(nativeForkAndSpecialize_orig)(
env, clazz, 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, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs env, clazz, 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, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
@ -80,7 +80,7 @@ jint nativeForkAndSpecialize_samsung_m(JNIEnv *env, jclass clazz, jint uid, jint
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir); AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_m)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_m)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir
@ -92,7 +92,7 @@ jint nativeForkAndSpecialize_samsung_n(JNIEnv *env, jclass clazz, jint uid, jint
AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir); AppSpecializeArgs_v3 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_n)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_n)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4 env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4
@ -105,7 +105,7 @@ jint nativeForkAndSpecialize_samsung_o(JNIEnv *env, jclass clazz, jint uid, jint
args.fds_to_ignore = &fds_to_ignore; args.fds_to_ignore = &fds_to_ignore;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_o)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_o)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
@ -119,7 +119,7 @@ jint nativeForkAndSpecialize_samsung_p(JNIEnv *env, jclass clazz, jint uid, jint
args.is_child_zygote = &is_child_zygote; args.is_child_zygote = &is_child_zygote;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre(); ctx.nativeForkAndSpecialize_pre();
reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_p)>(nativeForkAndSpecialize_orig)( reinterpret_cast<decltype(&nativeForkAndSpecialize_samsung_p)>(nativeForkAndSpecialize_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
@ -182,7 +182,7 @@ void nativeSpecializeAppProcess_q(JNIEnv *env, jclass clazz, jint uid, jint gid,
args.is_child_zygote = &is_child_zygote; args.is_child_zygote = &is_child_zygote;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre(); ctx.nativeSpecializeAppProcess_pre();
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q)>(nativeSpecializeAppProcess_orig)( reinterpret_cast<decltype(&nativeSpecializeAppProcess_q)>(nativeSpecializeAppProcess_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir
@ -195,7 +195,7 @@ void nativeSpecializeAppProcess_q_alt(JNIEnv *env, jclass clazz, jint uid, jint
args.is_top_app = &is_top_app; args.is_top_app = &is_top_app;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre(); ctx.nativeSpecializeAppProcess_pre();
reinterpret_cast<decltype(&nativeSpecializeAppProcess_q_alt)>(nativeSpecializeAppProcess_orig)( reinterpret_cast<decltype(&nativeSpecializeAppProcess_q_alt)>(nativeSpecializeAppProcess_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app
@ -212,7 +212,7 @@ void nativeSpecializeAppProcess_r(JNIEnv *env, jclass clazz, jint uid, jint gid,
args.mount_storage_dirs = &mount_storage_dirs; args.mount_storage_dirs = &mount_storage_dirs;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre(); ctx.nativeSpecializeAppProcess_pre();
reinterpret_cast<decltype(&nativeSpecializeAppProcess_r)>(nativeSpecializeAppProcess_orig)( reinterpret_cast<decltype(&nativeSpecializeAppProcess_r)>(nativeSpecializeAppProcess_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
@ -224,7 +224,7 @@ void nativeSpecializeAppProcess_samsung_q(JNIEnv *env, jclass clazz, jint uid, j
args.is_child_zygote = &is_child_zygote; args.is_child_zygote = &is_child_zygote;
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre(); ctx.nativeSpecializeAppProcess_pre();
reinterpret_cast<decltype(&nativeSpecializeAppProcess_samsung_q)>(nativeSpecializeAppProcess_orig)( reinterpret_cast<decltype(&nativeSpecializeAppProcess_samsung_q)>(nativeSpecializeAppProcess_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir
@ -260,7 +260,7 @@ jint nativeForkSystemServer_l(JNIEnv *env, jclass clazz, jint uid, jint gid, jin
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities); ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkSystemServer_pre(); ctx.nativeForkSystemServer_pre();
reinterpret_cast<decltype(&nativeForkSystemServer_l)>(nativeForkSystemServer_orig)( reinterpret_cast<decltype(&nativeForkSystemServer_l)>(nativeForkSystemServer_orig)(
env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities
@ -272,7 +272,7 @@ jint nativeForkSystemServer_samsung_q(JNIEnv *env, jclass clazz, jint uid, jint
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities); ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
HookContext ctx; HookContext ctx;
ctx.env = env; ctx.env = env;
ctx.raw_args = &args; ctx.args = { &args };
ctx.nativeForkSystemServer_pre(); ctx.nativeForkSystemServer_pre();
reinterpret_cast<decltype(&nativeForkSystemServer_samsung_q)>(nativeForkSystemServer_orig)( reinterpret_cast<decltype(&nativeForkSystemServer_samsung_q)>(nativeForkSystemServer_orig)(
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities

View File

@ -7,6 +7,18 @@ namespace {
struct HookContext; struct HookContext;
struct ZygiskModule; struct ZygiskModule;
struct AppSpecializeArgs_v1;
using AppSpecializeArgs_v2 = AppSpecializeArgs_v1;
struct AppSpecializeArgs_v3;
struct module_abi_v1;
using module_abi_v2 = module_abi_v1;
using module_abi_v3 = module_abi_v1;
struct api_abi_v1;
struct api_abi_v2;
using api_abi_v3 = api_abi_v2;
struct AppSpecializeArgs_v3 { struct AppSpecializeArgs_v3 {
jint &uid; jint &uid;
jint &gid; jint &gid;
@ -64,17 +76,6 @@ struct AppSpecializeArgs_v1 {
mount_data_dirs(v3->mount_data_dirs), mount_storage_dirs(v3->mount_storage_dirs) {} mount_data_dirs(v3->mount_data_dirs), mount_storage_dirs(v3->mount_storage_dirs) {}
}; };
struct module_abi_raw {
long api_version;
void *_this;
void (*preAppSpecialize)(void *, void *);
void (*postAppSpecialize)(void *, const void *);
void (*preServerSpecialize)(void *, void *);
void (*postServerSpecialize)(void *, const void *);
};
using module_abi_v1 = module_abi_raw;
struct ServerSpecializeArgs_v1 { struct ServerSpecializeArgs_v1 {
jint &uid; jint &uid;
jint &gid; jint &gid;
@ -91,6 +92,15 @@ struct ServerSpecializeArgs_v1 {
effective_capabilities(effective_capabilities) {} effective_capabilities(effective_capabilities) {}
}; };
struct module_abi_v1 {
long api_version;
void *impl;
void (*preAppSpecialize)(void *, void *);
void (*postAppSpecialize)(void *, const void *);
void (*preServerSpecialize)(void *, void *);
void (*postServerSpecialize)(void *, const void *);
};
enum : uint32_t { enum : uint32_t {
PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT, PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT,
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST, PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
@ -99,46 +109,47 @@ enum : uint32_t {
PROCESS_IS_MAGISK_APP = (1u << 31), PROCESS_IS_MAGISK_APP = (1u << 31),
UNMOUNT_MASK = (PROCESS_ON_DENYLIST | DENYLIST_ENFORCING), UNMOUNT_MASK = (PROCESS_ON_DENYLIST | DENYLIST_ENFORCING),
PRIVATE_MASK = (0x3u << 30) PRIVATE_MASK = (DENYLIST_ENFORCING | PROCESS_IS_MAGISK_APP)
}; };
struct ApiTable { struct api_abi_base {
// These first 2 entries are permanent ZygiskModule *impl;
ZygiskModule *module; bool (*registerModule)(api_abi_base *, long *);
bool (*registerModule)(ApiTable *, long *);
struct {
void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int);
void (*pltHookRegister)(const char *, const char *, void *, void **);
void (*pltHookExclude)(const char *, const char *);
bool (*pltHookCommit)();
int (*connectCompanion)(ZygiskModule *);
void (*setOption)(ZygiskModule *, zygisk::Option);
} v1{};
struct {
int (*getModuleDir)(ZygiskModule *);
uint32_t (*getFlags)(ZygiskModule *);
} v2{};
ApiTable(ZygiskModule *m);
}; };
#define call_app(method) \ struct api_abi_v1 : public api_abi_base {
switch (*ver) { \ void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int);
case 1: \ void (*pltHookRegister)(const char *, const char *, void *, void **);
case 2: { \ void (*pltHookExclude)(const char *, const char *);
AppSpecializeArgs_v1 a(args); \ bool (*pltHookCommit)();
v1->method(v1->_this, &a); \
break; \ int (*connectCompanion)(ZygiskModule *);
} \ void (*setOption)(ZygiskModule *, zygisk::Option);
case 3: \ };
v1->method(v1->_this, args); \
break; \ struct api_abi_v2 : public api_abi_v1 {
int (*getModuleDir)(ZygiskModule *);
uint32_t (*getFlags)(ZygiskModule *);
};
#define call_app(method) \
switch (*mod.api_version) { \
case 1: \
case 2: { \
AppSpecializeArgs_v1 a(args); \
mod.v1->method(mod.v1->impl, &a); \
break; \
} \
case 3: \
mod.v1->method(mod.v1->impl, args);\
break; \
} }
struct ZygiskModule { struct ZygiskModule {
void onLoad(void *env) {
entry.fn(&api, env);
}
void preAppSpecialize(AppSpecializeArgs_v3 *args) const { void preAppSpecialize(AppSpecializeArgs_v3 *args) const {
call_app(preAppSpecialize) call_app(preAppSpecialize)
} }
@ -146,37 +157,44 @@ struct ZygiskModule {
call_app(postAppSpecialize) call_app(postAppSpecialize)
} }
void preServerSpecialize(ServerSpecializeArgs_v1 *args) const { void preServerSpecialize(ServerSpecializeArgs_v1 *args) const {
v1->preServerSpecialize(v1->_this, args); mod.v1->preServerSpecialize(mod.v1->impl, args);
} }
void postServerSpecialize(const ServerSpecializeArgs_v1 *args) const { void postServerSpecialize(const ServerSpecializeArgs_v1 *args) const {
v1->postServerSpecialize(v1->_this, args); mod.v1->postServerSpecialize(mod.v1->impl, args);
} }
int connectCompanion() const; int connectCompanion() const;
int getModuleDir() const; int getModuleDir() const;
void setOption(zygisk::Option opt); void setOption(zygisk::Option opt);
static uint32_t getFlags(); static uint32_t getFlags();
void doUnload() const { if (unload) dlclose(handle); } void tryUnload() const { if (unload) dlclose(handle); }
void clearApi() { memset(&api, 0, sizeof(api)); }
int getId() const { return id; } int getId() const { return id; }
ZygiskModule(int id, void *handle, void *entry); ZygiskModule(int id, void *handle, void *entry);
static bool RegisterModule(ApiTable *table, long *module); static bool RegisterModule(api_abi_base *api, long *module);
union {
void (* const entry)(void *, void *);
void * const raw_entry;
};
ApiTable api;
private: private:
const int id; const int id;
bool unload = false; bool unload = false;
void * const handle; void * const handle;
union { union {
long *ver = nullptr; void * const ptr;
void (* const fn)(void *, void *);
} entry;
union {
api_abi_base base;
api_abi_v1 v1;
api_abi_v2 v2;
} api;
union {
long *api_version;
module_abi_v1 *v1; module_abi_v1 *v1;
}; } mod;
}; };
} // namespace } // namespace