Update Zygisk API to v2 (#1642)

This commit is contained in:
LoveSy 2022-02-08 01:26:56 +08:00 committed by GitHub
parent c11e760f7b
commit 6a16b2e346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 41 additions and 23 deletions

View File

@ -5,23 +5,17 @@
#include <jni.h> #include <jni.h>
#define ZYGISK_API_VERSION 1 #define ZYGISK_API_VERSION 2
/* /*
Define a class and inherit zygisk::ModuleBase to implement the functionality of your module. Define a class and inherit zygisk::ModuleBase to implement the functionality of your module.
Use the macro REGISTER_ZYGISK_MODULE(className) to register that class to Zygisk. Use the macro REGISTER_ZYGISK_MODULE(className) to register that class to Zygisk.
Please note that modules will only be loaded after zygote has forked the child process. Please note that modules will only be loaded after zygote has forked the child process.
THIS MEANS ALL OF YOUR CODE RUNS IN THE APP/SYSTEM SERVER PROCESS, NOT THE ZYGOTE DAEMON! THIS MEANS ALL OF YOUR CODE RUNS IN THE APP/SYSTEM SERVER PROCESS, NOT THE ZYGOTE DAEMON!
Example code: Example code:
static jint (*orig_logger_entry_max)(JNIEnv *env); static jint (*orig_logger_entry_max)(JNIEnv *env);
static jint my_logger_entry_max(JNIEnv *env) { return orig_logger_entry_max(env); } static jint my_logger_entry_max(JNIEnv *env) { return orig_logger_entry_max(env); }
static void example_handler(int socket) { ... } static void example_handler(int socket) { ... }
class ExampleModule : public zygisk::ModuleBase { class ExampleModule : public zygisk::ModuleBase {
public: public:
void onLoad(zygisk::Api *api, JNIEnv *env) override { void onLoad(zygisk::Api *api, JNIEnv *env) override {
@ -39,11 +33,8 @@ private:
zygisk::Api *api; zygisk::Api *api;
JNIEnv *env; JNIEnv *env;
}; };
REGISTER_ZYGISK_MODULE(ExampleModule) REGISTER_ZYGISK_MODULE(ExampleModule)
REGISTER_ZYGISK_COMPANION(example_handler) REGISTER_ZYGISK_COMPANION(example_handler)
*/ */
namespace zygisk { namespace zygisk {
@ -58,7 +49,7 @@ namespace zygisk {
// This function is called when the module is loaded into the target process. // This function is called when the module is loaded into the target process.
// A Zygisk API handle will be sent as an argument; call utility functions or interface // A Zygisk API handle will be sent as an argument; call utility functions or interface
// with Zygisk through this handle. // with Zygisk through this handle.
virtual void onLoad(Api *api, JNIEnv *env) {} virtual void onLoad([[maybe_unused]] Api *api, [[maybe_unused]] JNIEnv *env) {}
// This function is called before the app process is specialized. // This function is called before the app process is specialized.
// At this point, the process just got forked from zygote, but no app specific specialization // At this point, the process just got forked from zygote, but no app specific specialization
@ -72,20 +63,20 @@ namespace zygisk {
// If you need to run some operations as superuser, you can call Api::connectCompanion() to // If you need to run some operations as superuser, you can call Api::connectCompanion() to
// get a socket to do IPC calls with a root companion process. // get a socket to do IPC calls with a root companion process.
// See Api::connectCompanion() for more info. // See Api::connectCompanion() for more info.
virtual void preAppSpecialize(AppSpecializeArgs *args) {} virtual void preAppSpecialize([[maybe_unused]] AppSpecializeArgs *args) {}
// This function is called after the app process is specialized. // This function is called after the app process is specialized.
// At this point, the process has all sandbox restrictions enabled for this application. // At this point, the process has all sandbox restrictions enabled for this application.
// This means that this function runs as the same privilege of the app's own code. // This means that this function runs as the same privilege of the app's own code.
virtual void postAppSpecialize(const AppSpecializeArgs *args) {} virtual void postAppSpecialize([[maybe_unused]] const AppSpecializeArgs *args) {}
// This function is called before the system server process is specialized. // This function is called before the system server process is specialized.
// See preAppSpecialize(args) for more info. // See preAppSpecialize(args) for more info.
virtual void preServerSpecialize(ServerSpecializeArgs *args) {} virtual void preServerSpecialize([[maybe_unused]] ServerSpecializeArgs *args) {}
// This function is called after the system server process is specialized. // This function is called after the system server process is specialized.
// At this point, the process runs with the privilege of system_server. // At this point, the process runs with the privilege of system_server.
virtual void postServerSpecialize(const ServerSpecializeArgs *args) {} virtual void postServerSpecialize([[maybe_unused]] const ServerSpecializeArgs *args) {}
}; };
struct AppSpecializeArgs { struct AppSpecializeArgs {
@ -134,20 +125,25 @@ namespace zygisk {
// Setting this option only makes sense in preAppSpecialize. // Setting this option only makes sense in preAppSpecialize.
// The actual unmounting happens during app process specialization. // The actual unmounting happens during app process specialization.
// //
// Processes added to Magisk's denylist will have all Magisk and its modules' files unmounted // Set this option to force all Magisk and modules' files to be unmounted from the
// from its mount namespace. In addition, all Zygisk code will be unloaded from memory, which // mount namespace of the process, regardless of the denylist enforcement status.
// also implies that no Zygisk modules (including yours) are loaded.
//
// However, if for any reason your module still wants the unmount part of the denylist
// operation to be enabled EVEN IF THE PROCESS IS NOT ON THE DENYLIST, set this option.
FORCE_DENYLIST_UNMOUNT = 0, FORCE_DENYLIST_UNMOUNT = 0,
// When this option is set, your module's library will be dlclose-ed after post[XXX]Specialize. // When this option is set, your module's library will be dlclose-ed after post[XXX]Specialize.
// Be aware that after dlclose-ing your module, all of your code will be unmapped. // Be aware that after dlclose-ing your module, all of your code will be unmapped from memory.
// YOU SHOULD NOT ENABLE THIS OPTION AFTER HOOKING ANY FUNCTION IN THE PROCESS. // YOU MUST NOT ENABLE THIS OPTION AFTER HOOKING ANY FUNCTIONS IN THE PROCESS.
DLCLOSE_MODULE_LIBRARY = 1, DLCLOSE_MODULE_LIBRARY = 1,
}; };
// Bit masks of the return value of Api::getFlags()
enum StateFlag : uint32_t {
// The user has granted root access to the current process
PROCESS_GRANTED_ROOT = (1u << 0),
// The current process was added on the denylist
PROCESS_ON_DENYLIST = (1u << 1),
};
// All API functions will stop working after post[XXX]Specialize as Zygisk will be unloaded // All API functions will stop working after post[XXX]Specialize as Zygisk will be unloaded
// from the specialized process afterwards. // from the specialized process afterwards.
struct Api { struct Api {
@ -169,11 +165,25 @@ namespace zygisk {
// module's companion request handler. Returns -1 if the connection attempt failed. // module's companion request handler. Returns -1 if the connection attempt failed.
int connectCompanion(); int connectCompanion();
// Get the file descriptor of the root folder of the current module.
//
// This API only works in the pre[XXX]Specialize functions.
// Accessing the directory returned is only possible in the pre[XXX]Specialize functions
// or in the root companion process (assuming that you sent the fd over the socket).
// Both restrictions are due to SELinux and UID.
//
// Returns -1 if errors occurred.
int getModuleDir();
// Set various options for your module. // Set various options for your module.
// Please note that this function accepts one single option at a time. // Please note that this function accepts one single option at a time.
// Check zygisk::Option for the full list of options available. // Check zygisk::Option for the full list of options available.
void setOption(Option opt); void setOption(Option opt);
// Get information about the current process.
// Returns bitwise-or'd zygisk::StateFlag values.
uint32_t getFlags();
// Hook JNI native methods for a class // Hook JNI native methods for a class
// //
// Lookup all registered JNI native methods and replace it with your own functions. // Lookup all registered JNI native methods and replace it with your own functions.
@ -257,6 +267,8 @@ void zygisk_companion_entry(int client) { func(client); }
// Zygisk functions // Zygisk functions
int (*connectCompanion)(void * /* _this */); int (*connectCompanion)(void * /* _this */);
void (*setOption)(void * /* _this */, Option); void (*setOption)(void * /* _this */, Option);
int (*getModuleDir)(void * /* _this */);
uint32_t (*getFlags)(void * /* _this */);
}; };
template <class T> template <class T>
@ -274,9 +286,15 @@ void zygisk_companion_entry(int client) { func(client); }
inline int Api::connectCompanion() { inline int Api::connectCompanion() {
return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1; return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1;
} }
inline int Api::getModuleDir() {
return impl->getModuleDir ? impl->getModuleDir(impl->_this) : -1;
}
inline void Api::setOption(Option opt) { inline void Api::setOption(Option opt) {
if (impl->setOption) impl->setOption(impl->_this, opt); if (impl->setOption) impl->setOption(impl->_this, opt);
} }
inline uint32_t Api::getFlags() {
return impl->getFlags ? impl->getFlags(impl->_this) : 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 (impl->hookJniNativeMethods) impl->hookJniNativeMethods(env, className, methods, numMethods);
} }