mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-21 09:38:30 +00:00
Implement Zygisk companion process
This commit is contained in:
parent
6f54c57647
commit
d0fc372ecd
@ -32,6 +32,7 @@ LOCAL_SRC_FILES := \
|
|||||||
zygisk/utils.cpp \
|
zygisk/utils.cpp \
|
||||||
zygisk/hook.cpp \
|
zygisk/hook.cpp \
|
||||||
zygisk/memory.cpp \
|
zygisk/memory.cpp \
|
||||||
|
zygisk/companion.cpp \
|
||||||
zygisk/deny/cli.cpp \
|
zygisk/deny/cli.cpp \
|
||||||
zygisk/deny/utils.cpp \
|
zygisk/deny/utils.cpp \
|
||||||
zygisk/deny/revert.cpp
|
zygisk/deny/revert.cpp
|
||||||
|
@ -27,7 +27,7 @@ int fork_no_orphan() {
|
|||||||
int pid = xfork();
|
int pid = xfork();
|
||||||
if (pid)
|
if (pid)
|
||||||
return pid;
|
return pid;
|
||||||
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||||
if (getppid() == 1)
|
if (getppid() == 1)
|
||||||
exit(1);
|
exit(1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -141,12 +141,8 @@ struct Api {
|
|||||||
// Another good use case for a companion process is that if you want to share some resources
|
// Another good use case for a companion process is that if you want to share some resources
|
||||||
// across multiple processes, hold the resources in the companion process and pass it over.
|
// across multiple processes, hold the resources in the companion process and pass it over.
|
||||||
//
|
//
|
||||||
// When this function is called, in the companion process, a socket pair will be created,
|
// Returns a file descriptor to a socket that is connected to the socket passed to your
|
||||||
// your module's onCompanionRequest(int) callback will receive one socket, and the other
|
// module's companion request handler. Returns -1 if the connection attempt failed.
|
||||||
// socket will be returned.
|
|
||||||
//
|
|
||||||
// Returns a file descriptor to a socket that is connected to the socket passed to
|
|
||||||
// your module's onCompanionRequest(int). Returns -1 if the connection attempt failed.
|
|
||||||
int connectCompanion();
|
int connectCompanion();
|
||||||
|
|
||||||
// Force Magisk's denylist unmount routines to run on this process.
|
// Force Magisk's denylist unmount routines to run on this process.
|
||||||
|
91
native/jni/zygisk/companion.cpp
Normal file
91
native/jni/zygisk/companion.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <utils.hpp>
|
||||||
|
#include <socket.hpp>
|
||||||
|
#include <daemon.hpp>
|
||||||
|
|
||||||
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static int zygiskd_socket = -1;
|
||||||
|
|
||||||
|
[[noreturn]] static void zygiskd(int socket) {
|
||||||
|
set_nice_name("zygiskd");
|
||||||
|
LOGI("* Launching zygiskd\n");
|
||||||
|
|
||||||
|
// Load modules
|
||||||
|
using comp_entry = void(*)(int);
|
||||||
|
vector<comp_entry> modules;
|
||||||
|
{
|
||||||
|
#if defined(__LP64__)
|
||||||
|
vector<int> module_fds = zygisk_module_fds(true);
|
||||||
|
#else
|
||||||
|
vector<int> module_fds = zygisk_module_fds(false);
|
||||||
|
#endif
|
||||||
|
char buf[256];
|
||||||
|
for (int fd : module_fds) {
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
|
||||||
|
comp_entry entry = nullptr;
|
||||||
|
if (void *h = dlopen(buf, RTLD_LAZY)) {
|
||||||
|
*(void **) &entry = dlsym(h, "zygisk_companion_entry");
|
||||||
|
}
|
||||||
|
modules.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start accepting requests
|
||||||
|
pollfd pfd = { socket, POLLIN, 0 };
|
||||||
|
for (;;) {
|
||||||
|
poll(&pfd, 1, -1);
|
||||||
|
if (!(pfd.revents & POLLIN)) {
|
||||||
|
// Something bad happened in magiskd, terminate zygiskd
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
int client = recv_fd(socket);
|
||||||
|
int module_id = read_int(client);
|
||||||
|
if (module_id < modules.size() && modules[module_id]) {
|
||||||
|
exec_task([=, entry = modules[module_id]] {
|
||||||
|
int dup = fcntl(client, F_DUPFD_CLOEXEC);
|
||||||
|
entry(client);
|
||||||
|
// Only close client if it is the same as dup so we don't
|
||||||
|
// accidentally close a re-used file descriptor.
|
||||||
|
// This check is required because the module companion
|
||||||
|
// handler could've closed the file descriptor already.
|
||||||
|
if (struct stat s1; fstat(client, &s1) == 0) {
|
||||||
|
struct stat s2{};
|
||||||
|
fstat(dup, &s2);
|
||||||
|
if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
|
||||||
|
close(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(dup);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
close(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_companion(int client) {
|
||||||
|
if (zygiskd_socket >= 0) {
|
||||||
|
// Make sure the socket is still valid
|
||||||
|
pollfd pfd = { zygiskd_socket, 0, 0 };
|
||||||
|
poll(&pfd, 1, 0);
|
||||||
|
if (pfd.revents) {
|
||||||
|
// Any revent means error
|
||||||
|
close(zygiskd_socket);
|
||||||
|
zygiskd_socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (zygiskd_socket < 0) {
|
||||||
|
int fds[2];
|
||||||
|
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
|
||||||
|
zygiskd_socket = fds[0];
|
||||||
|
if (fork_dont_care() == 0) {
|
||||||
|
zygiskd(fds[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
send_fd(zygiskd_socket, client);
|
||||||
|
}
|
@ -349,6 +349,9 @@ void zygisk_handler(int client, ucred *cred) {
|
|||||||
case ZYGISK_GET_LOG_PIPE:
|
case ZYGISK_GET_LOG_PIPE:
|
||||||
send_log_pipe(client);
|
send_log_pipe(client);
|
||||||
break;
|
break;
|
||||||
|
case ZYGISK_START_COMPANION:
|
||||||
|
start_companion(client);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
@ -284,9 +284,13 @@ bool ZygiskModule::registerModule(ApiTable *table, long *module) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ZygiskModule::connectCompanion() {
|
int ZygiskModule::connectCompanion() const {
|
||||||
// TODO
|
if (int fd = connect_daemon(); fd >= 0) {
|
||||||
(void) id;
|
write_int(fd, ZYGISK_REQUEST);
|
||||||
|
write_int(fd, ZYGISK_START_COMPANION);
|
||||||
|
write_int(fd, id);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ struct ZygiskModule {
|
|||||||
v1->postServerSpecialize(v1->_this, force_cast(args));
|
v1->postServerSpecialize(v1->_this, force_cast(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
int connectCompanion();
|
int connectCompanion() const;
|
||||||
static void forceDenyListUnmount();
|
static void forceDenyListUnmount();
|
||||||
static bool registerModule(ApiTable *table, long *module);
|
static bool registerModule(ApiTable *table, long *module);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ enum : int {
|
|||||||
ZYGISK_GET_INFO,
|
ZYGISK_GET_INFO,
|
||||||
ZYGISK_UNMOUNT,
|
ZYGISK_UNMOUNT,
|
||||||
ZYGISK_GET_LOG_PIPE,
|
ZYGISK_GET_LOG_PIPE,
|
||||||
|
ZYGISK_START_COMPANION,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
@ -46,3 +47,4 @@ void hook_functions();
|
|||||||
bool unhook_functions();
|
bool unhook_functions();
|
||||||
std::vector<int> remote_get_info(int uid, const char *process, AppInfo *info);
|
std::vector<int> remote_get_info(int uid, const char *process, AppInfo *info);
|
||||||
int remote_request_unmount();
|
int remote_request_unmount();
|
||||||
|
void start_companion(int client);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user