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 install_apk(const char *apk);
[[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
--path print Magisk tmpfs mount path
--denylist ARGS denylist config CLI
--companion FD start zygisk root companion
Available applets:
)EOF");
@ -127,6 +128,8 @@ int magisk_main(int argc, char *argv[]) {
return 0;
} else if (argc >= 3 && argv[1] == "--install-module"sv) {
install_module(argv[2]);
} else if (argc >= 3 && argv[1] == "--companion"sv) {
zygiskd(parse_int(argv[2]));
}
#if 0
/* Entry point for testing stuffs */

View File

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

View File

@ -79,9 +79,7 @@ public:
bool operator!=(const stateless_allocator&) { return false; }
};
int parse_int(const char *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()); }
int parse_int(std::string_view s);
using thread_entry = void *(*)(void *);
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
// 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
// module's companion request handler. Returns -1 if the connection attempt failed.
int connectCompanion();

View File

@ -4,26 +4,30 @@
#include <utils.hpp>
#include <socket.hpp>
#include <daemon.hpp>
#include <magisk.hpp>
#include "zygisk.hpp"
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) {
set_nice_name("zygiskd");
LOGI("* Launching zygiskd\n");
#if defined(__LP64__)
set_nice_name("zygiskd64");
LOGI("* Launching zygiskd64\n");
#else
set_nice_name("zygiskd32");
LOGI("* Launching zygiskd32\n");
#endif
// 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
vector<int> module_fds = recv_fds(socket);
char buf[256];
for (int fd : module_fds) {
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
pollfd pfd = { socket, POLLIN, 0 };
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) {
// Make sure the socket is still valid
pollfd pfd = { zygiskd_socket, 0, 0 };
@ -84,7 +94,20 @@ void start_companion(int client) {
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
zygiskd_socket = fds[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);

View File

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

View File

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

View File

@ -12,7 +12,7 @@ enum : int {
ZYGISK_GET_INFO,
ZYGISK_UNMOUNT,
ZYGISK_GET_LOG_PIPE,
ZYGISK_START_COMPANION,
ZYGISK_CONNECT_COMPANION,
};
#if defined(__LP64__)
@ -47,4 +47,4 @@ void hook_functions();
bool unhook_functions();
std::vector<int> remote_get_info(int uid, const char *process, AppInfo *info);
int remote_request_unmount();
void start_companion(int client);
void connect_companion(int client, bool is_64_bit);