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

View File

@ -97,7 +97,7 @@ class ForkAndSpec(JNIHook):
decl += ind(1) + f'args.{a.name} = &{a.name};'
decl += ind(1) + 'HookContext ctx;'
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) + self.orig_method() + '('
decl += ind(2) + f'env, clazz, {self.name_list()}'

View File

@ -43,10 +43,10 @@ void name##_post();
struct HookContext {
JNIEnv *env;
union {
AppSpecializeArgs_v3 *args;
ServerSpecializeArgs_v1 *server_args;
void *raw_args;
};
void *ptr;
AppSpecializeArgs_v3 *app;
ServerSpecializeArgs_v1 *server;
} args;
const char *process;
vector<ZygiskModule> modules;
bitset<FLAG_MAX> state;
@ -54,7 +54,7 @@ struct HookContext {
int pid;
uint32_t flags;
HookContext() : pid(-1), flags(0) {}
HookContext() : env(nullptr), args{nullptr}, process(nullptr), pid(-1), flags(0) {}
static void close_fds();
void unload_zygisk();
@ -280,39 +280,49 @@ void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods
}
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)
: module(m), registerModule(&ZygiskModule::RegisterModule) {}
bool ZygiskModule::RegisterModule(ApiTable *table, long *module) {
long ver = *module;
bool ZygiskModule::RegisterModule(api_abi_base *api, long *module) {
long api_version = *module;
// Unsupported version
if (ver > ZYGISK_API_VERSION)
if (api_version > ZYGISK_API_VERSION)
return false;
// Set the actual module_abi*
table->module->ver = module;
api->impl->mod = { module };
// Fill in API accordingly with module API version
switch (ver) {
switch (api_version) {
case 3:
case 2:
table->v2.getModuleDir = [](ZygiskModule *m) { return m->getModuleDir(); };
table->v2.getFlags = [](auto) { return ZygiskModule::getFlags(); };
case 2: {
auto v2 = static_cast<api_abi_v2 *>(api);
v2->getModuleDir = [](ZygiskModule *m) { return m->getModuleDir(); };
v2->getFlags = [](auto) { return ZygiskModule::getFlags(); };
}
// fallthrough
case 1:
table->v1.hookJniNativeMethods = &hookJniNativeMethods;
table->v1.pltHookRegister = [](const char *p, const char *s, void *n, void **o) {
case 1: {
auto v1 = static_cast<api_abi_v1 *>(api);
v1->hookJniNativeMethods = &hookJniNativeMethods;
v1->pltHookRegister = [](const char *p, const char *s, void *n, void **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);
};
table->v1.pltHookCommit = []{ bool r = xhook_refresh(0) == 0; xhook_clear(); return r; };
table->v1.connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); };
table->v1.setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); };
v1->pltHookCommit = [] {
bool r = xhook_refresh(0) == 0;
xhook_clear();
return r;
};
v1->connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); };
v1->setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); };
break;
}
default:
// Unknown version number
return false;
@ -395,17 +405,17 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
}
for (auto &m : modules) {
m.entry(&m.api, env);
m.onLoad(env);
if (state[APP_SPECIALIZE]) {
m.preAppSpecialize(args);
m.preAppSpecialize(args.app);
} else if (state[SERVER_SPECIALIZE]) {
m.preServerSpecialize(server_args);
m.preServerSpecialize(args.server);
}
}
// Add all ignored fd onto whitelist
if (state[APP_SPECIALIZE] && args->fds_to_ignore) {
if (jintArray fdsToIgnore = *args->fds_to_ignore) {
if (state[APP_SPECIALIZE] && args.app->fds_to_ignore) {
if (jintArray fdsToIgnore = *args.app->fds_to_ignore) {
int len = env->GetArrayLength(fdsToIgnore);
int *arr = env->GetIntArrayElements(fdsToIgnore, nullptr);
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() {
for (const auto &m : modules) {
if (state[APP_SPECIALIZE]) {
m.postAppSpecialize(args);
m.postAppSpecialize(args.app);
} 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
for (auto &m : modules) {
memset(&m.api, 0, sizeof(m.api));
m.clearApi();
}
new_daemon_thread(reinterpret_cast<thread_entry>(&dlclose), self_handle);
@ -464,7 +474,7 @@ void HookContext::unload_zygisk() {
void HookContext::nativeSpecializeAppProcess_pre() {
g_ctx = this;
state[APP_SPECIALIZE] = true;
process = env->GetStringUTFChars(args->nice_name, nullptr);
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
if (state[FORK_AND_SPECIALIZE]) {
ZLOGV("pre forkAndSpecialize [%s]\n", process);
} else {
@ -472,7 +482,7 @@ void HookContext::nativeSpecializeAppProcess_pre() {
}
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) {
ZLOGI("[%s] is on the denylist\n", process);
state[DO_UNMOUNT] = true;
@ -492,7 +502,7 @@ void HookContext::nativeSpecializeAppProcess_post() {
ZLOGV("post specialize [%s]\n", process);
}
env->ReleaseStringUTFChars(args->nice_name, process);
env->ReleaseStringUTFChars(args.app->nice_name, process);
run_modules_post();
if (flags & PROCESS_IS_MAGISK_APP) {
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);
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -20,7 +20,7 @@ jint nativeForkAndSpecialize_o(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.fds_to_ignore = &fds_to_ignore;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -34,7 +34,7 @@ jint nativeForkAndSpecialize_p(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.is_child_zygote = &is_child_zygote;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -49,7 +49,7 @@ jint nativeForkAndSpecialize_q_alt(JNIEnv *env, jclass clazz, jint uid, jint gid
args.is_top_app = &is_top_app;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -68,7 +68,7 @@ jint nativeForkAndSpecialize_r(JNIEnv *env, jclass clazz, jint uid, jint gid, ji
args.mount_storage_dirs = &mount_storage_dirs;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -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);
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -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);
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -105,7 +105,7 @@ jint nativeForkAndSpecialize_samsung_o(JNIEnv *env, jclass clazz, jint uid, jint
args.fds_to_ignore = &fds_to_ignore;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -119,7 +119,7 @@ jint nativeForkAndSpecialize_samsung_p(JNIEnv *env, jclass clazz, jint uid, jint
args.is_child_zygote = &is_child_zygote;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkAndSpecialize_pre();
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
@ -182,7 +182,7 @@ void nativeSpecializeAppProcess_q(JNIEnv *env, jclass clazz, jint uid, jint gid,
args.is_child_zygote = &is_child_zygote;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre();
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
@ -195,7 +195,7 @@ void nativeSpecializeAppProcess_q_alt(JNIEnv *env, jclass clazz, jint uid, jint
args.is_top_app = &is_top_app;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre();
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
@ -212,7 +212,7 @@ void nativeSpecializeAppProcess_r(JNIEnv *env, jclass clazz, jint uid, jint gid,
args.mount_storage_dirs = &mount_storage_dirs;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre();
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
@ -224,7 +224,7 @@ void nativeSpecializeAppProcess_samsung_q(JNIEnv *env, jclass clazz, jint uid, j
args.is_child_zygote = &is_child_zygote;
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeSpecializeAppProcess_pre();
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
@ -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);
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkSystemServer_pre();
reinterpret_cast<decltype(&nativeForkSystemServer_l)>(nativeForkSystemServer_orig)(
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);
HookContext ctx;
ctx.env = env;
ctx.raw_args = &args;
ctx.args = { &args };
ctx.nativeForkSystemServer_pre();
reinterpret_cast<decltype(&nativeForkSystemServer_samsung_q)>(nativeForkSystemServer_orig)(
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities

View File

@ -7,6 +7,18 @@ namespace {
struct HookContext;
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 {
jint &uid;
jint &gid;
@ -64,17 +76,6 @@ struct AppSpecializeArgs_v1 {
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 {
jint &uid;
jint &gid;
@ -91,6 +92,15 @@ struct ServerSpecializeArgs_v1 {
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 {
PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT,
PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST,
@ -99,46 +109,47 @@ enum : uint32_t {
PROCESS_IS_MAGISK_APP = (1u << 31),
UNMOUNT_MASK = (PROCESS_ON_DENYLIST | DENYLIST_ENFORCING),
PRIVATE_MASK = (0x3u << 30)
PRIVATE_MASK = (DENYLIST_ENFORCING | PROCESS_IS_MAGISK_APP)
};
struct ApiTable {
// These first 2 entries are permanent
ZygiskModule *module;
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);
struct api_abi_base {
ZygiskModule *impl;
bool (*registerModule)(api_abi_base *, long *);
};
#define call_app(method) \
switch (*ver) { \
case 1: \
case 2: { \
AppSpecializeArgs_v1 a(args); \
v1->method(v1->_this, &a); \
break; \
} \
case 3: \
v1->method(v1->_this, args); \
break; \
struct api_abi_v1 : public api_abi_base {
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);
};
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 {
void onLoad(void *env) {
entry.fn(&api, env);
}
void preAppSpecialize(AppSpecializeArgs_v3 *args) const {
call_app(preAppSpecialize)
}
@ -146,37 +157,44 @@ struct ZygiskModule {
call_app(postAppSpecialize)
}
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 {
v1->postServerSpecialize(v1->_this, args);
mod.v1->postServerSpecialize(mod.v1->impl, args);
}
int connectCompanion() const;
int getModuleDir() const;
void setOption(zygisk::Option opt);
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; }
ZygiskModule(int id, void *handle, void *entry);
static bool RegisterModule(ApiTable *table, long *module);
union {
void (* const entry)(void *, void *);
void * const raw_entry;
};
ApiTable api;
static bool RegisterModule(api_abi_base *api, long *module);
private:
const int id;
bool unload = false;
void * const handle;
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;
};
} mod;
};
} // namespace