Make zygiskd ABI aware

This commit is contained in:
topjohnwu 2021-10-23 14:38:30 -07:00
parent 4194ac894c
commit 7496d51580
9 changed files with 61 additions and 26 deletions

View File

@ -34,3 +34,6 @@ void exec_common_scripts(const char *stage);
void exec_module_scripts(const char *stage, const std::vector<std::string_view> &modules); void exec_module_scripts(const char *stage, const std::vector<std::string_view> &modules);
void install_apk(const char *apk); void install_apk(const char *apk);
[[noreturn]] void install_module(const char *file); [[noreturn]] void install_module(const char *file);
// Zygisk companion entrypoint
[[noreturn]] void zygiskd(int socket);

View File

@ -39,6 +39,7 @@ Advanced Options (Internal APIs):
--sqlite SQL exec SQL commands to Magisk database --sqlite SQL exec SQL commands to Magisk database
--path print Magisk tmpfs mount path --path print Magisk tmpfs mount path
--denylist ARGS denylist config CLI --denylist ARGS denylist config CLI
--companion FD start zygisk root companion
Available applets: Available applets:
)EOF"); )EOF");
@ -127,6 +128,8 @@ int magisk_main(int argc, char *argv[]) {
return 0; return 0;
} else if (argc >= 3 && argv[1] == "--install-module"sv) { } else if (argc >= 3 && argv[1] == "--install-module"sv) {
install_module(argv[2]); install_module(argv[2]);
} else if (argc >= 3 && argv[1] == "--companion"sv) {
zygiskd(parse_int(argv[2]));
} }
#if 0 #if 0
/* Entry point for testing stuffs */ /* Entry point for testing stuffs */

View File

@ -138,10 +138,10 @@ void set_nice_name(const char *name) {
* Bionic's atoi runs through strtol(). * Bionic's atoi runs through strtol().
* Use our own implementation for faster conversion. * Use our own implementation for faster conversion.
*/ */
int parse_int(const char *s) { int parse_int(string_view s) {
int val = 0; int val = 0;
char c; for (char c : s) {
while ((c = *(s++))) { if (!c) break;
if (c > '9' || c < '0') if (c > '9' || c < '0')
return -1; return -1;
val = val * 10 + c - '0'; val = val * 10 + c - '0';

View File

@ -79,9 +79,7 @@ public:
bool operator!=(const stateless_allocator&) { return false; } bool operator!=(const stateless_allocator&) { return false; }
}; };
int parse_int(const char *s); int parse_int(std::string_view s);
static inline int parse_int(const std::string &s) { return parse_int(s.data()); }
static inline int parse_int(std::string_view s) { return parse_int(s.data()); }
using thread_entry = void *(*)(void *); using thread_entry = void *(*)(void *);
int new_daemon_thread(thread_entry entry, void *arg = nullptr); int new_daemon_thread(thread_entry entry, void *arg = nullptr);

View File

@ -164,6 +164,9 @@ 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.
// //
// The root companion process is ABI aware; that is, when calling this function from a 32-bit
// process, you will be connected to a 32-bit companion process, and vice versa for 64-bit.
//
// Returns a file descriptor to a socket that is connected to the socket passed to your // Returns a file descriptor to a socket that is connected to the socket passed to your
// 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();

View File

@ -4,26 +4,30 @@
#include <utils.hpp> #include <utils.hpp>
#include <socket.hpp> #include <socket.hpp>
#include <daemon.hpp> #include <daemon.hpp>
#include <magisk.hpp>
#include "zygisk.hpp" #include "zygisk.hpp"
using namespace std; using namespace std;
static int zygiskd_socket = -1; void zygiskd(int socket) {
if (getuid() != 0 || fcntl(socket, F_GETFD) < 0)
exit(-1);
android_logging();
[[noreturn]] static void zygiskd(int socket) { #if defined(__LP64__)
set_nice_name("zygiskd"); set_nice_name("zygiskd64");
LOGI("* Launching zygiskd\n"); LOGI("* Launching zygiskd64\n");
#else
set_nice_name("zygiskd32");
LOGI("* Launching zygiskd32\n");
#endif
// Load modules // Load modules
using comp_entry = void(*)(int); using comp_entry = void(*)(int);
vector<comp_entry> modules; vector<comp_entry> modules;
{ {
#if defined(__LP64__) vector<int> module_fds = recv_fds(socket);
vector<int> module_fds = zygisk_module_fds(true);
#else
vector<int> module_fds = zygisk_module_fds(false);
#endif
char buf[256]; char buf[256];
for (int fd : module_fds) { for (int fd : module_fds) {
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
@ -35,6 +39,9 @@ static int zygiskd_socket = -1;
} }
} }
// ack
write_int(socket, 0);
// Start accepting requests // Start accepting requests
pollfd pfd = { socket, POLLIN, 0 }; pollfd pfd = { socket, POLLIN, 0 };
for (;;) { for (;;) {
@ -68,7 +75,10 @@ static int zygiskd_socket = -1;
} }
} }
void start_companion(int client) { static int zygiskd_sockets[] = { -1, -1 };
#define zygiskd_socket zygiskd_sockets[is_64_bit]
void connect_companion(int client, bool is_64_bit) {
if (zygiskd_socket >= 0) { if (zygiskd_socket >= 0) {
// Make sure the socket is still valid // Make sure the socket is still valid
pollfd pfd = { zygiskd_socket, 0, 0 }; pollfd pfd = { zygiskd_socket, 0, 0 };
@ -84,7 +94,20 @@ void start_companion(int client) {
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
zygiskd_socket = fds[0]; zygiskd_socket = fds[0];
if (fork_dont_care() == 0) { if (fork_dont_care() == 0) {
zygiskd(fds[1]); string exe = MAGISKTMP + "/magisk" + (is_64_bit ? "64" : "32");
// This fd has to survive exec
fcntl(fds[1], F_SETFD, 0);
char buf[16];
snprintf(buf, sizeof(buf), "%d", fds[1]);
execlp(exe.data(), "magisk", "--companion", buf, (char *) nullptr);
exit(-1);
}
close(fds[1]);
vector<int> module_fds = zygisk_module_fds(is_64_bit);
send_fds(zygiskd_socket, module_fds.data(), module_fds.size());
// Wait for ack
if (read_int(zygiskd_socket) != 0) {
return;
} }
} }
send_fd(zygiskd_socket, client); send_fd(zygiskd_socket, client);

View File

@ -243,12 +243,16 @@ int remote_request_unmount() {
// The following code runs in magiskd // The following code runs in magiskd
static bool get_exe(int pid, char *buf, size_t sz) {
snprintf(buf, sz, "/proc/%d/exe", pid);
return xreadlink(buf, buf, sz) > 0;
}
static void setup_files(int client, const sock_cred *cred) { static void setup_files(int client, const sock_cred *cred) {
LOGD("zygisk: setup files for pid=[%d]\n", cred->pid); LOGD("zygisk: setup files for pid=[%d]\n", cred->pid);
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "/proc/%d/exe", cred->pid); if (!get_exe(cred->pid, buf, sizeof(buf))) {
if (xreadlink(buf, buf, sizeof(buf)) < 0) {
write_int(client, 1); write_int(client, 1);
return; return;
} }
@ -308,8 +312,7 @@ static void get_process_info(int client, const sock_cred *cred) {
if (!info.on_denylist) { if (!info.on_denylist) {
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "/proc/%d/exe", cred->pid); get_exe(cred->pid, buf, sizeof(buf));
xreadlink(buf, buf, sizeof(buf));
vector<int> fds = zygisk_module_fds(str_ends(buf, "64")); vector<int> fds = zygisk_module_fds(str_ends(buf, "64"));
send_fds(client, fds.data(), fds.size()); send_fds(client, fds.data(), fds.size());
} }
@ -336,6 +339,7 @@ static void send_log_pipe(int fd) {
void zygisk_handler(int client, const sock_cred *cred) { void zygisk_handler(int client, const sock_cred *cred) {
int code = read_int(client); int code = read_int(client);
char buf[256];
switch (code) { switch (code) {
case ZYGISK_SETUP: case ZYGISK_SETUP:
setup_files(client, cred); setup_files(client, cred);
@ -349,8 +353,9 @@ void zygisk_handler(int client, const sock_cred *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: case ZYGISK_CONNECT_COMPANION:
start_companion(client); get_exe(cred->pid, buf, sizeof(buf));
connect_companion(client, str_ends(buf, "64"));
break; break;
} }
close(client); close(client);

View File

@ -290,7 +290,7 @@ bool ZygiskModule::registerModule(ApiTable *table, long *module) {
int ZygiskModule::connectCompanion() const { int ZygiskModule::connectCompanion() const {
if (int fd = connect_daemon(); fd >= 0) { if (int fd = connect_daemon(); fd >= 0) {
write_int(fd, ZYGISK_REQUEST); write_int(fd, ZYGISK_REQUEST);
write_int(fd, ZYGISK_START_COMPANION); write_int(fd, ZYGISK_CONNECT_COMPANION);
write_int(fd, id); write_int(fd, id);
return fd; return fd;
} }

View File

@ -12,7 +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, ZYGISK_CONNECT_COMPANION,
}; };
#if defined(__LP64__) #if defined(__LP64__)
@ -47,4 +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); void connect_companion(int client, bool is_64_bit);