You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
fix: zygiskd companion, companion responses, write fd function and early client close
This commit fixes numerous issues in zygiskd code: The zygiskd companion code not loading the right entry, the companion not sending the correct responses, the write fd function not working properly and early client close when connecting to the companion.
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
#include <linux/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "dl.h"
|
||||
@@ -17,36 +21,45 @@ namespace zygiskd {
|
||||
}
|
||||
|
||||
int Connect(uint8_t retry) {
|
||||
retry++;
|
||||
|
||||
int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = { 0 },
|
||||
.sun_path = { 0 }
|
||||
};
|
||||
|
||||
auto socket_path = TMP_PATH + kCPSocketName;
|
||||
strcpy(addr.sun_path, socket_path.c_str());
|
||||
socklen_t socklen = sizeof(addr);
|
||||
|
||||
while (retry--) {
|
||||
int r = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), socklen);
|
||||
while (--retry) {
|
||||
int r = connect(fd, (struct sockaddr *)&addr, socklen);
|
||||
if (r == 0) return fd;
|
||||
if (retry) {
|
||||
PLOGE("Retrying to connect to zygiskd, sleep 1s");
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool PingHeartbeat() {
|
||||
UniqueFd fd = Connect(5);
|
||||
int fd = Connect(5);
|
||||
if (fd == -1) {
|
||||
PLOGE("Connect to zygiskd");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::PingHeartBeat);
|
||||
|
||||
close(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,31 +67,42 @@ namespace zygiskd {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("RequestLogcatFd");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestLogcatFd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint32_t GetProcessFlags(uid_t uid) {
|
||||
UniqueFd fd = Connect(1);
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("GetProcessFlags");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetProcessFlags);
|
||||
socket_utils::write_u32(fd, uid);
|
||||
|
||||
return socket_utils::read_u32(fd);
|
||||
uint32_t res = socket_utils::read_u32(fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<Module> ReadModules() {
|
||||
std::vector<Module> modules;
|
||||
UniqueFd fd = Connect(1);
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("ReadModules");
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadModules);
|
||||
size_t len = socket_utils::read_usize(fd);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
@@ -86,6 +110,9 @@ namespace zygiskd {
|
||||
int module_fd = socket_utils::recv_fd(fd);
|
||||
modules.emplace_back(name, module_fd);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
@@ -93,53 +120,64 @@ namespace zygiskd {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("ConnectCompanion");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestCompanionSocket);
|
||||
socket_utils::write_usize(fd, index);
|
||||
if (socket_utils::read_u8(fd) == 1) {
|
||||
return fd;
|
||||
} else {
|
||||
|
||||
uint8_t res = socket_utils::read_u8(fd);
|
||||
|
||||
if (res == 1) return fd;
|
||||
else {
|
||||
close(fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int GetModuleDir(size_t index) {
|
||||
UniqueFd fd = Connect(1);
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("GetModuleDir");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetModuleDir);
|
||||
socket_utils::write_usize(fd, index);
|
||||
return socket_utils::recv_fd(fd);
|
||||
int nfd = socket_utils::recv_fd(fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return nfd;
|
||||
}
|
||||
|
||||
void ZygoteRestart() {
|
||||
UniqueFd fd = Connect(1);
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
LOGD("Could not notify ZygoteRestart (maybe it hasn't been created)");
|
||||
} else {
|
||||
PLOGE("Could not notify ZygoteRestart");
|
||||
}
|
||||
if (errno == ENOENT) LOGD("Could not notify ZygoteRestart (maybe it hasn't been created)");
|
||||
else PLOGE("Could not notify ZygoteRestart");
|
||||
|
||||
return;
|
||||
}
|
||||
if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart)) {
|
||||
|
||||
if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart))
|
||||
PLOGE("Failed to request ZygoteRestart");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void SystemServerStarted() {
|
||||
UniqueFd fd = Connect(1);
|
||||
if (fd == -1) {
|
||||
PLOGE("Failed to report system server started");
|
||||
} else {
|
||||
if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::SystemServerStarted)) {
|
||||
int fd = Connect(1);
|
||||
if (fd == -1) PLOGE("Failed to report system server started");
|
||||
else {
|
||||
if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::SystemServerStarted))
|
||||
PLOGE("Failed to report system server started");
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void GetInfo(struct zygote_info *info) {
|
||||
@@ -147,6 +185,8 @@ namespace zygiskd {
|
||||
int fd = Connect(1);
|
||||
|
||||
if (fd != -1) {
|
||||
info->running = true;
|
||||
|
||||
socket_utils::write_u8(fd, (uint8_t) SocketAction::GetInfo);
|
||||
|
||||
int flags = socket_utils::read_u32(fd);
|
||||
@@ -161,6 +201,8 @@ namespace zygiskd {
|
||||
info->root_impl = ZYGOTE_ROOT_IMPL_NONE;
|
||||
}
|
||||
|
||||
info->pid = socket_utils::read_u32(fd);
|
||||
|
||||
info->modules = (struct zygote_modules *)malloc(sizeof(struct zygote_modules));
|
||||
if (info->modules == NULL) {
|
||||
info->modules->modules_count = 0;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "socket_utils.h"
|
||||
|
||||
namespace socket_utils {
|
||||
|
||||
ssize_t xread(int fd, void* buf, size_t count) {
|
||||
size_t read_sz = 0;
|
||||
ssize_t ret;
|
||||
@@ -48,33 +47,6 @@ namespace socket_utils {
|
||||
return rec;
|
||||
}
|
||||
|
||||
void* recv_fds(int sockfd, char* cmsgbuf, size_t bufsz, int cnt) {
|
||||
iovec iov = {
|
||||
.iov_base = &cnt,
|
||||
.iov_len = sizeof(cnt),
|
||||
};
|
||||
msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = bufsz
|
||||
};
|
||||
|
||||
xrecvmsg(sockfd, &msg, MSG_WAITALL);
|
||||
cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
if (msg.msg_controllen != bufsz ||
|
||||
cmsg == nullptr ||
|
||||
// TODO: pass from rust: 20, expected: 16
|
||||
// cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) ||
|
||||
cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CMSG_DATA(cmsg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T read_exact_or(int fd, T fail) {
|
||||
T res;
|
||||
@@ -103,10 +75,13 @@ namespace socket_utils {
|
||||
}
|
||||
|
||||
std::string read_string(int fd) {
|
||||
auto len = read_usize(fd);
|
||||
size_t len = read_usize(fd);
|
||||
|
||||
char buf[len + 1];
|
||||
buf[len] = '\0';
|
||||
xread(fd, buf, len);
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -114,12 +89,31 @@ namespace socket_utils {
|
||||
return write_exact<uint8_t>(fd, val);
|
||||
}
|
||||
|
||||
bool write_u32(int fd, uint32_t val) {
|
||||
return write_exact<uint32_t>(fd, val);
|
||||
void* recv_fds(int sockfd, char* cmsgbuf, size_t bufsz, int cnt) {
|
||||
iovec iov = {
|
||||
.iov_base = &cnt,
|
||||
.iov_len = sizeof(cnt),
|
||||
};
|
||||
msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = bufsz
|
||||
};
|
||||
|
||||
xrecvmsg(sockfd, &msg, MSG_WAITALL);
|
||||
cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
if (msg.msg_controllen != bufsz ||
|
||||
cmsg == nullptr ||
|
||||
// TODO: pass from rust: 20, expected: 16
|
||||
// cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) ||
|
||||
cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool write_string(int fd, std::string_view str) {
|
||||
return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size());
|
||||
return CMSG_DATA(cmsg);
|
||||
}
|
||||
|
||||
int recv_fd(int sockfd) {
|
||||
@@ -132,4 +126,12 @@ namespace socket_utils {
|
||||
memcpy(&result, data, sizeof(int));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool write_u32(int fd, uint32_t val) {
|
||||
return write_exact<uint32_t>(fd, val);
|
||||
}
|
||||
|
||||
bool write_string(int fd, std::string_view str) {
|
||||
return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ fun getLatestNDKPath(): String {
|
||||
}
|
||||
|
||||
// get 2nd latest version
|
||||
val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(1)
|
||||
val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(2)
|
||||
return ndkPath + "/" + ndkVersion
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <linux/limits.h>
|
||||
@@ -19,6 +20,11 @@
|
||||
|
||||
typedef void (*zygisk_companion_entry_func)(int);
|
||||
|
||||
struct companion_module_thread_args {
|
||||
int fd;
|
||||
zygisk_companion_entry_func entry;
|
||||
};
|
||||
|
||||
zygisk_companion_entry_func load_module(int fd) {
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
|
||||
@@ -30,101 +36,100 @@ zygisk_companion_entry_func load_module(int fd) {
|
||||
return (zygisk_companion_entry_func)entry;
|
||||
}
|
||||
|
||||
void *call_entry(void *restrict arg) {
|
||||
int fd = *((int *)arg);
|
||||
void *entry_thread(void *arg) {
|
||||
struct companion_module_thread_args *args = (struct companion_module_thread_args *)arg;
|
||||
|
||||
int fd = args->fd;
|
||||
zygisk_companion_entry_func module_entry = args->entry;
|
||||
|
||||
struct stat st0;
|
||||
if (fstat(fd, &st0) == -1) {
|
||||
LOGE("Failed to stat client fd\n");
|
||||
fstat(fd, &st0);
|
||||
|
||||
free(arg);
|
||||
LOGI("New companion thread (inside the thread!).\n - Client fd: %d\n", fd);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
entry(fd);
|
||||
module_entry(fd);
|
||||
|
||||
// Only close client if it is the same file 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.
|
||||
/* TODO: Is this even necessary? */
|
||||
struct stat st1;
|
||||
if (fstat(fd, &st1) == -1) {
|
||||
LOGE("Failed to stat client fd\n");
|
||||
|
||||
free(arg);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (fstat(fd, &st1) != -1) {
|
||||
if (st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino) {
|
||||
close(fd);
|
||||
|
||||
LOGI("Client fd has been replaced. Bye!\n");
|
||||
}
|
||||
}
|
||||
|
||||
free(arg);
|
||||
free(args);
|
||||
|
||||
pthread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void entry(int fd) {
|
||||
LOGI("companion entry fd: |%d|\n", fd);
|
||||
LOGI("New companion entry.\n - Client fd: %d\n", fd);
|
||||
|
||||
char name[256 + 1];
|
||||
ssize_t ret = read_string(fd, name, sizeof(name) - 1);
|
||||
if (ret == -1) return;
|
||||
char name[256];
|
||||
ssize_t ret = read_string(fd, name, sizeof(name));
|
||||
if (ret == -1) {
|
||||
LOGE("Failed to read module name\n");
|
||||
|
||||
name[ret] = '\0';
|
||||
|
||||
LOGI("Companion process requested for `%s`\n", name);
|
||||
|
||||
int library_fd;
|
||||
recv_fd(fd, &library_fd);
|
||||
|
||||
LOGI("Library fd: %d\n", library_fd);
|
||||
|
||||
zygisk_companion_entry_func entry = load_module(library_fd);
|
||||
|
||||
LOGI("Library loaded\n");
|
||||
|
||||
close(library_fd);
|
||||
|
||||
LOGI("Library closed\n");
|
||||
|
||||
if (entry == NULL) {
|
||||
LOGI("No companion entry for: %s\n", name);
|
||||
|
||||
uint8_t response = 0;
|
||||
uint8_t response = 2;
|
||||
write(fd, &response, sizeof(response));
|
||||
|
||||
exit(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Companion process created for: %s\n", name);
|
||||
LOGI(" - Module name: `%.*s`\n", (int)ret, name);
|
||||
|
||||
uint8_t response = 1;
|
||||
int library_fd = gread_fd(fd);
|
||||
if (library_fd == -1) {
|
||||
LOGE("Failed to receive library fd\n");
|
||||
|
||||
uint8_t response = 2;
|
||||
write(fd, &response, sizeof(response));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
LOGI(" - Library fd: %d\n", library_fd);
|
||||
|
||||
zygisk_companion_entry_func module_entry = load_module(library_fd);
|
||||
close(library_fd);
|
||||
|
||||
if (module_entry == NULL) {
|
||||
LOGI("No companion module entry for module: %.*s\n", (int)ret, name);
|
||||
|
||||
write_int(fd, 0);
|
||||
|
||||
exit(0);
|
||||
} else {
|
||||
write_int(fd, 1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!check_unix_socket(fd, true)) {
|
||||
LOGI("Something went wrong. Bye!\n");
|
||||
LOGI("Something went wrong in companion. Bye!\n");
|
||||
|
||||
exit(0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
int *client_fd = malloc(sizeof(int));
|
||||
recv_fd(fd, client_fd);
|
||||
struct companion_module_thread_args *args = malloc(sizeof(struct companion_module_thread_args));
|
||||
args->entry = module_entry;
|
||||
|
||||
LOGI("New companion request from module \"%s\" with fd \"%d\"\n", name, *client_fd);
|
||||
if ((args->fd = gread_fd(fd)) == -1) {
|
||||
LOGE("Failed to receive client fd\n");
|
||||
|
||||
write(fd, &response, sizeof(response));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
LOGI("Creating new thread for companion request\n");
|
||||
LOGI("New companion request.\n - Module name: %.*s\n - Client fd: %d\n", (int)ret, name, args->fd);
|
||||
|
||||
write_uint8_t(args->fd, 1);
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, call_entry, (void *)client_fd);
|
||||
pthread_detach(thread);
|
||||
pthread_create(&thread, NULL, entry_thread, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "companion.h"
|
||||
#include "dl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define ANDROID_NAMESPACE_TYPE_SHARED 0x2
|
||||
#define ANDROID_DLEXT_USE_NAMESPACE 0x200
|
||||
|
||||
struct AndroidNamespace {
|
||||
u_int8_t _unused[0];
|
||||
};
|
||||
typedef struct AndroidNamespace {
|
||||
unsigned char _unused[0];
|
||||
} AndroidNamespace;
|
||||
|
||||
struct AndroidDlextinfo {
|
||||
u_int64_t flags;
|
||||
typedef struct AndroidDlextinfo {
|
||||
uint64_t flags;
|
||||
void *reserved_addr;
|
||||
size_t reserved_size;
|
||||
int relro_fd;
|
||||
int library_fd;
|
||||
off64_t library_fd_offset;
|
||||
struct AndroidNamespace *library_namespace;
|
||||
};
|
||||
AndroidNamespace *library_namespace;
|
||||
} AndroidDlextinfo;
|
||||
|
||||
void *android_dlopen_ext(const char *filename, int flags, const struct AndroidDlextinfo *extinfo);
|
||||
extern void *android_dlopen_ext(const char *filename, int flags, const AndroidDlextinfo *extinfo);
|
||||
|
||||
void *android_dlopen(char *restrict path, uint32_t flags) {
|
||||
typedef AndroidNamespace *(*AndroidCreateNamespaceFn)(
|
||||
const char *name,
|
||||
const char *ld_library_path,
|
||||
const char *default_library_path,
|
||||
uint64_t type,
|
||||
const char *permitted_when_isolated_path,
|
||||
AndroidNamespace *parent,
|
||||
const void *caller_addr
|
||||
);
|
||||
|
||||
void *android_dlopen(char *path, int flags) {
|
||||
char *dir = dirname(path);
|
||||
struct AndroidDlextinfo info = {
|
||||
.flags = 0,
|
||||
@@ -35,24 +57,32 @@ void *android_dlopen(char *restrict path, uint32_t flags) {
|
||||
.library_namespace = NULL,
|
||||
};
|
||||
|
||||
void *android_create_namespace_fn = dlsym(RTLD_DEFAULT, "__loader_android_create_namespace");
|
||||
void *handle = dlsym(RTLD_DEFAULT, "__loader_android_create_namespace");
|
||||
AndroidCreateNamespaceFn android_create_namespace_fn = (AndroidCreateNamespaceFn)handle;
|
||||
|
||||
if (android_create_namespace_fn != NULL) {
|
||||
void *ns = ((void *(*)(const char *, const char *, const char *, u_int32_t, void *, void *, void *))android_create_namespace_fn)(
|
||||
AndroidNamespace *ns = android_create_namespace_fn(
|
||||
path,
|
||||
dir,
|
||||
NULL,
|
||||
ANDROID_NAMESPACE_TYPE_SHARED,
|
||||
NULL,
|
||||
NULL,
|
||||
(void *)&android_dlopen
|
||||
(const void *)&android_dlopen
|
||||
);
|
||||
|
||||
if (ns != NULL) {
|
||||
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||
info.library_namespace = ns;
|
||||
}
|
||||
|
||||
LOGI("Open %s with namespace %p\n", path, (void *)ns);
|
||||
} else {
|
||||
LOGI("Cannot create namespace for %s\n", path);
|
||||
}
|
||||
|
||||
return android_dlopen_ext(path, flags, &info);
|
||||
void *result = android_dlopen_ext(path, flags, &info);
|
||||
if (result == NULL) {
|
||||
LOGE("Failed to dlopen %s: %s\n", path, dlerror());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef DL_H
|
||||
#define DL_H
|
||||
|
||||
void *android_dlopen(char *restrict path, u_int32_t flags);
|
||||
void *android_dlopen(char *path, int flags);
|
||||
|
||||
#endif /* DL_H */
|
||||
|
||||
@@ -86,7 +86,7 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
root_impls_setup();
|
||||
zygiskd_start();
|
||||
zygiskd_start(argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char line[1024];
|
||||
char line[1024 * 2];
|
||||
/* INFO: Skip the CSV header */
|
||||
fgets(line, sizeof(line), fp);
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/* INFO 50ms wait */
|
||||
// #define ALLOW_WAIT_ON_DEBUG() usleep(500 * 1000)
|
||||
#define ALLOW_WAIT_ON_DEBUG() {}
|
||||
|
||||
bool switch_mount_namespace(pid_t pid) {
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
|
||||
@@ -192,82 +196,114 @@ int unix_listener_from_path(char *restrict path) {
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
ssize_t send_fd(int sockfd, int fd) {
|
||||
char control_buf[CMSG_SPACE(sizeof(int))];
|
||||
memset(control_buf, 0, sizeof(control_buf));
|
||||
ssize_t gwrite_fd(int fd, int sendfd) {
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
char buf[1] = { 0 };
|
||||
|
||||
int cnt = 1;
|
||||
struct iovec iov = {
|
||||
.iov_base = &cnt,
|
||||
.iov_len = sizeof(cnt)
|
||||
.iov_base = buf,
|
||||
.iov_len = 1
|
||||
};
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = control_buf,
|
||||
.msg_controllen = sizeof(control_buf)
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = sizeof(cmsgbuf)
|
||||
};
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &sendfd, sizeof(int));
|
||||
|
||||
ssize_t sent_bytes = sendmsg(sockfd, &msg, 0);
|
||||
if (sent_bytes == -1) {
|
||||
LOGE("Failed to send fd: %s\n", strerror(errno));
|
||||
ssize_t ret = sendmsg(fd, &msg, 0);
|
||||
if (ret == -1) {
|
||||
LOGE("sendmsg: %s\n", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sent_bytes;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t recv_fd(int sockfd, int *restrict fd) {
|
||||
char control_buf[CMSG_SPACE(sizeof(int))];
|
||||
memset(control_buf, 0, sizeof(control_buf));
|
||||
int gread_fd(int fd) {
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
char buf[1] = { 0 };
|
||||
|
||||
int cnt = 1;
|
||||
struct iovec iov = {
|
||||
.iov_base = &cnt,
|
||||
.iov_len = sizeof(cnt)
|
||||
.iov_base = buf,
|
||||
.iov_len = 1
|
||||
};
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = control_buf,
|
||||
.msg_controllen = sizeof(control_buf)
|
||||
.msg_control = cmsgbuf,
|
||||
.msg_controllen = sizeof(cmsgbuf)
|
||||
};
|
||||
|
||||
ssize_t received_bytes = recvmsg(sockfd, &msg, 0);
|
||||
if (received_bytes == -1) {
|
||||
LOGE("Failed to read fd: %s\n", strerror(errno));
|
||||
ssize_t ret = recvmsg(fd, &msg, 0);
|
||||
if (ret == -1) {
|
||||
LOGE("recvmsg: %s\n", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
|
||||
|
||||
return received_bytes;
|
||||
}
|
||||
|
||||
ssize_t write_string(int fd, const char *restrict str) {
|
||||
size_t len = strlen(str);
|
||||
|
||||
ssize_t written_bytes = write(fd, &len, sizeof(len));
|
||||
if (written_bytes != sizeof(len)) {
|
||||
LOGE("Failed to write string length: %s\n", strerror(errno));
|
||||
if (cmsg == NULL) {
|
||||
LOGE("CMSG_FIRSTHDR: %s\n", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
written_bytes = write(fd, str, len);
|
||||
if ((size_t)written_bytes != len) {
|
||||
int sendfd;
|
||||
memcpy(&sendfd, CMSG_DATA(cmsg), sizeof(int));
|
||||
|
||||
return sendfd;
|
||||
}
|
||||
|
||||
#define write_func(type) \
|
||||
ssize_t write_## type(int fd, type val) { \
|
||||
ALLOW_WAIT_ON_DEBUG(); \
|
||||
\
|
||||
return write(fd, &val, sizeof(type)); \
|
||||
}
|
||||
|
||||
#define read_func(type) \
|
||||
ssize_t read_## type(int fd, type *val) { \
|
||||
return read(fd, val, sizeof(type)); \
|
||||
}
|
||||
|
||||
write_func(int)
|
||||
read_func(int)
|
||||
|
||||
write_func(size_t)
|
||||
read_func(size_t)
|
||||
|
||||
write_func(uint32_t)
|
||||
read_func(uint32_t)
|
||||
|
||||
write_func(uint8_t)
|
||||
read_func(uint8_t)
|
||||
|
||||
ssize_t write_string(int fd, const char *restrict str) {
|
||||
size_t len[1];
|
||||
len[0] = strlen(str);
|
||||
|
||||
ALLOW_WAIT_ON_DEBUG();
|
||||
|
||||
ssize_t written_bytes = write(fd, &len, sizeof(size_t));
|
||||
if (written_bytes != sizeof(size_t)) {
|
||||
LOGE("Failed to write string length: Not all bytes were written (%zd != %zu).\n", written_bytes, sizeof(size_t));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
written_bytes = write(fd, str, len[0]);
|
||||
if ((size_t)written_bytes != len[0]) {
|
||||
LOGE("Failed to write string: Not all bytes were written.\n");
|
||||
|
||||
return -1;
|
||||
@@ -279,9 +315,9 @@ ssize_t write_string(int fd, const char *restrict str) {
|
||||
ssize_t read_string(int fd, char *restrict str, size_t len) {
|
||||
size_t str_len_buf[1];
|
||||
|
||||
ssize_t read_bytes = read(fd, &str_len_buf, sizeof(str_len_buf));
|
||||
if (read_bytes != (ssize_t)sizeof(str_len_buf)) {
|
||||
LOGE("Failed to read string length: %s\n", strerror(errno));
|
||||
ssize_t read_bytes = read(fd, &str_len_buf, sizeof(size_t));
|
||||
if (read_bytes != (ssize_t)sizeof(size_t)) {
|
||||
LOGE("Failed to read string length: Not all bytes were read (%zd != %zu).\n", read_bytes, sizeof(size_t));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -296,7 +332,7 @@ ssize_t read_string(int fd, char *restrict str, size_t len) {
|
||||
|
||||
read_bytes = read(fd, str, str_len);
|
||||
if (read_bytes != (ssize_t)str_len) {
|
||||
LOGE("Failed to read string: Not all bytes were read (%zd != %zu).\n", read_bytes, str_len);
|
||||
LOGE("Failed to read string: Promised bytes doesn't exist (%zd != %zu).\n", read_bytes, str_len);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -349,7 +385,7 @@ bool check_unix_socket(int fd, bool block) {
|
||||
int timeout = block ? -1 : 0;
|
||||
poll(&pfd, 1, timeout);
|
||||
|
||||
return (pfd.revents & !POLLIN) != 0 ? false : true;
|
||||
return pfd.revents & ~POLLIN ? false : true;
|
||||
}
|
||||
|
||||
/* INFO: Cannot use restrict here as execv does not have restrict */
|
||||
|
||||
@@ -14,10 +14,16 @@
|
||||
FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__))
|
||||
|
||||
#define LOGE(...) \
|
||||
__android_log_print(ANDROID_LOG_INFO , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
||||
__android_log_print(ANDROID_LOG_ERROR , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \
|
||||
printf(__VA_ARGS__); \
|
||||
FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__))
|
||||
|
||||
#define write_func_def(type) \
|
||||
ssize_t write_## type(int fd, type val)
|
||||
|
||||
#define read_func_def(type) \
|
||||
ssize_t read_## type(int fd, type *val)
|
||||
|
||||
bool switch_mount_namespace(pid_t pid);
|
||||
|
||||
void get_property(const char *name, char *restrict output);
|
||||
@@ -30,9 +36,25 @@ int chcon(const char *path, const char *restrict context);
|
||||
|
||||
int unix_listener_from_path(char *path);
|
||||
|
||||
ssize_t send_fd(int sockfd, int fd);
|
||||
// ssize_t send_fd(int sockfd, int fd);
|
||||
|
||||
ssize_t recv_fd(int sockfd, int *restrict fd);
|
||||
// int recv_fd(int sockfd);
|
||||
|
||||
ssize_t gwrite_fd(int fd, int sendfd);
|
||||
|
||||
int gread_fd(int fd);
|
||||
|
||||
write_func_def(int);
|
||||
read_func_def(int);
|
||||
|
||||
write_func_def(size_t);
|
||||
read_func_def(size_t);
|
||||
|
||||
write_func_def(uint32_t);
|
||||
read_func_def(uint32_t);
|
||||
|
||||
write_func_def(uint8_t);
|
||||
read_func_def(uint8_t);
|
||||
|
||||
ssize_t write_string(int fd, const char *restrict str);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <sys/sendfile.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <linux/limits.h>
|
||||
@@ -173,26 +174,10 @@ static void load_modules(enum Architecture arch, struct Context *restrict contex
|
||||
|
||||
char arch_str[32];
|
||||
switch (arch) {
|
||||
case ARM32: {
|
||||
strcpy(arch_str, "armeabi-v7a");
|
||||
|
||||
break;
|
||||
}
|
||||
case ARM64: {
|
||||
strcpy(arch_str, "arm64-v8a");
|
||||
|
||||
break;
|
||||
}
|
||||
case X86: {
|
||||
strcpy(arch_str, "x86");
|
||||
|
||||
break;
|
||||
}
|
||||
case X86_64: {
|
||||
strcpy(arch_str, "x86_64");
|
||||
|
||||
break;
|
||||
}
|
||||
case ARM64: { strcpy(arch_str, "arm64-v8a"); break; }
|
||||
case X86_64: { strcpy(arch_str, "x86_64"); break; }
|
||||
case ARM32: { strcpy(arch_str, "armeabi-v7a"); break; }
|
||||
case X86: { strcpy(arch_str, "x86"); break; }
|
||||
}
|
||||
|
||||
LOGI("Loading modules for architecture: %s\n", arch_str);
|
||||
@@ -258,7 +243,9 @@ static int create_daemon_socket(void) {
|
||||
return unix_listener_from_path(PATH_CP_NAME);
|
||||
}
|
||||
|
||||
static int spawn_companion(char *restrict name, int lib_fd) {
|
||||
static int spawn_companion(char *restrict argv[], char *restrict name, int lib_fd) {
|
||||
LOGI("Spawning a new companion...\n");
|
||||
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
|
||||
LOGE("Failed creating socket pair.\n");
|
||||
@@ -269,11 +256,7 @@ static int spawn_companion(char *restrict name, int lib_fd) {
|
||||
int daemon_fd = sockets[0];
|
||||
int companion_fd = sockets[1];
|
||||
|
||||
LOGI("Companion fd: %d\n", companion_fd);
|
||||
LOGI("Daemon fd: %d\n", daemon_fd);
|
||||
|
||||
pid_t pid = fork();
|
||||
LOGI("Forked: %d\n", pid);
|
||||
if (pid < 0) {
|
||||
LOGE("Failed forking companion: %s\n", strerror(errno));
|
||||
|
||||
@@ -284,66 +267,83 @@ static int spawn_companion(char *restrict name, int lib_fd) {
|
||||
} else if (pid > 0) {
|
||||
close(companion_fd);
|
||||
|
||||
LOGI("Waiting for companion to start (%d)\n", pid);
|
||||
|
||||
int status = 0;
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
LOGI("Companion exited with status %d\n", status);
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (write_string(daemon_fd, name) == -1) {
|
||||
LOGE("Failed sending module name\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
if (send_fd(daemon_fd, lib_fd) == -1) {
|
||||
LOGE("Failed sending lib fd\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGI("Sent module name and lib fd\n");
|
||||
|
||||
uint8_t response_buf[1];
|
||||
ssize_t ret = read(daemon_fd, &response_buf, sizeof(response_buf));
|
||||
ASSURE_SIZE_READ_WR("companion", "response", ret, sizeof(response_buf));
|
||||
|
||||
LOGI("Companion response: %hhu\n", response_buf[0]);
|
||||
|
||||
if (response_buf[0] == 0) {
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
} else if (response_buf[0] == 1) return daemon_fd;
|
||||
else {
|
||||
LOGE("Invalid response from companion: %hhu\n", response_buf[0]);
|
||||
LOGE("Failed writing module name.\n");
|
||||
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
if (gwrite_fd(daemon_fd, lib_fd) == -1) {
|
||||
LOGE("Failed sending library fd.\n");
|
||||
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t response = 0;
|
||||
ssize_t ret = read_uint8_t(daemon_fd, &response);
|
||||
if (ret <= 0) {
|
||||
LOGE("Failed reading companion response.\n");
|
||||
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGI("Companion response: %hhu\n", response);
|
||||
|
||||
switch (response) {
|
||||
/* INFO: Even without any entry, we should still just deal with it */
|
||||
case 0: { return -2; }
|
||||
case 1: { return daemon_fd; }
|
||||
/* TODO: Should we be closing daemon socket here? (in non-0-and-1 case) */
|
||||
default: {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* TODO: Should we be closing daemon socket here? */
|
||||
} else {
|
||||
LOGE("Exited with status %d\n", status);
|
||||
|
||||
close(daemon_fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/* INFO: if pid == 0: */
|
||||
} else {
|
||||
LOGI("Companion started\n");
|
||||
/* INFO: There is no case where this will fail with a valid fd. */
|
||||
fcntl(companion_fd, F_SETFD, 0);
|
||||
/* INFO: Remove FD_CLOEXEC flag to avoid closing upon exec */
|
||||
if (fcntl(companion_fd, F_SETFD, 0) == -1) {
|
||||
LOGE("Failed removing FD_CLOEXEC flag: %s\n", strerror(errno));
|
||||
|
||||
close(companion_fd);
|
||||
close(daemon_fd);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *process = argv[0];
|
||||
char nice_name[256];
|
||||
char *last = strrchr(process, '/');
|
||||
if (last == NULL) {
|
||||
snprintf(nice_name, sizeof(nice_name), "%s", process);
|
||||
} else {
|
||||
snprintf(nice_name, sizeof(nice_name), "%s", last + 1);
|
||||
}
|
||||
|
||||
char process_name[256];
|
||||
snprintf(process_name, sizeof(process_name), "%s-%s", nice_name, name);
|
||||
|
||||
char companion_fd_str[32];
|
||||
snprintf(companion_fd_str, 32, "%d", companion_fd);
|
||||
snprintf(companion_fd_str, sizeof(companion_fd_str), "%d", companion_fd);
|
||||
|
||||
LOGI("Executing companion...\n");
|
||||
|
||||
char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL };
|
||||
if (non_blocking_execv(ZYGISKD_PATH, argv) == -1) {
|
||||
char *eargv[] = { process_name, "companion", companion_fd_str, NULL };
|
||||
if (non_blocking_execv(ZYGISKD_PATH, eargv) == -1) {
|
||||
LOGE("Failed executing companion: %s\n", strerror(errno));
|
||||
|
||||
close(companion_fd);
|
||||
@@ -351,8 +351,6 @@ static int spawn_companion(char *restrict name, int lib_fd) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LOGI("Bye bye!\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -362,7 +360,7 @@ struct __attribute__((__packed__)) MsgHead {
|
||||
char data[0];
|
||||
};
|
||||
|
||||
void zygiskd_start(void) {
|
||||
void zygiskd_start(char *restrict argv[]) {
|
||||
LOGI("Welcome to ReZygisk %s!\n", ZKSU_VERSION);
|
||||
|
||||
enum RootImpl impl = get_impl();
|
||||
@@ -517,10 +515,8 @@ void zygiskd_start(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Accepted client: %d\n", client_fd);
|
||||
|
||||
uint8_t buf[1];
|
||||
ssize_t len = read(client_fd, buf, sizeof(buf));
|
||||
uint8_t action8 = 0;
|
||||
ssize_t len = read_uint8_t(client_fd, &action8);
|
||||
if (len == -1) {
|
||||
LOGE("read: %s\n", strerror(errno));
|
||||
|
||||
@@ -531,17 +527,22 @@ void zygiskd_start(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Action: %hhu\n", buf[0]);
|
||||
enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0];
|
||||
enum DaemonSocketAction action = (enum DaemonSocketAction)action8;
|
||||
|
||||
switch (action) {
|
||||
case PingHeartbeat: {
|
||||
LOGI("ZD-- PingHeartbeat\n");
|
||||
|
||||
enum DaemonSocketAction msgr = ZYGOTE_INJECTED;
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction));
|
||||
|
||||
LOGI("ZD++ PingHeartbeat\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case ZygoteRestart: {
|
||||
LOGI("ZD-- ZygoteRestart\n");
|
||||
|
||||
for (int i = 0; i < context.len; i++) {
|
||||
if (context.modules[i].companion != -1) {
|
||||
close(context.modules[i].companion);
|
||||
@@ -549,36 +550,40 @@ void zygiskd_start(void) {
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("ZD++ ZygoteRestart\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case SystemServerStarted: {
|
||||
LOGI("ZD-- SystemServerStarted\n");
|
||||
|
||||
enum DaemonSocketAction msgr = SYSTEM_SERVER_STARTED;
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction));
|
||||
|
||||
LOGI("ZD++ SystemServerStarted\n");
|
||||
|
||||
break;
|
||||
}
|
||||
/* TODO: May need to move to another thread? :/ */
|
||||
case RequestLogcatFd: {
|
||||
uint8_t level_buf[1];
|
||||
ssize_t ret = read(client_fd, &level_buf, sizeof(level_buf));
|
||||
ASSURE_SIZE_READ_BREAK("RequestLogcatFd", "level", ret, sizeof(level_buf));
|
||||
|
||||
uint8_t level = level_buf[0];
|
||||
uint8_t level = 0;
|
||||
ssize_t ret = read_uint8_t(client_fd, &level);
|
||||
ASSURE_SIZE_READ_BREAK("RequestLogcatFd", "level", ret, sizeof(level));
|
||||
|
||||
char tag[128 + 1];
|
||||
ret = read_string(client_fd, tag, sizeof(tag) - 1);
|
||||
if (ret == -1) {
|
||||
LOGE("Failed reading tag\n");
|
||||
LOGE("Failed reading logcat tag.\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
tag[ret] = '\0';
|
||||
|
||||
/* INFO: Non-NULL terminated */
|
||||
char message[1024];
|
||||
ret = read_string(client_fd, message, sizeof(message));
|
||||
if (ret == -1) {
|
||||
LOGE("Failed reading message\n");
|
||||
LOGE("Failed reading logcat message.\n");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -588,13 +593,11 @@ void zygiskd_start(void) {
|
||||
break;
|
||||
}
|
||||
case GetProcessFlags: {
|
||||
LOGI("Getting process flags\n");
|
||||
LOGI("ZD-- GetProcessFlags\n");
|
||||
|
||||
uint32_t uid_buf[1];
|
||||
ssize_t ret = read(client_fd, &uid_buf, sizeof(uid_buf));
|
||||
ASSURE_SIZE_READ_BREAK("GetProcessFlags", "uid", ret, sizeof(uid_buf));
|
||||
|
||||
uint32_t uid = uid_buf[0];
|
||||
uint32_t uid = 0;
|
||||
ssize_t ret = read_uint32_t(client_fd, &uid);
|
||||
ASSURE_SIZE_READ_BREAK("GetProcessFlags", "uid", ret, sizeof(uid));
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (uid_is_manager(uid)) {
|
||||
@@ -608,8 +611,6 @@ void zygiskd_start(void) {
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("Flags for uid %d: %d\n", uid, flags);
|
||||
|
||||
switch (get_impl()) {
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
@@ -630,17 +631,17 @@ void zygiskd_start(void) {
|
||||
}
|
||||
}
|
||||
|
||||
ret = write(client_fd, &flags, sizeof(flags));
|
||||
ret = write_int(client_fd, flags);
|
||||
ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags));
|
||||
|
||||
LOGI("Sent flags\n");
|
||||
LOGI("ZD++ GetProcessFlags\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case GetInfo: {
|
||||
uint32_t flags = 0;
|
||||
LOGI("ZD-- GetInfo\n");
|
||||
|
||||
LOGI("Getting info\n");
|
||||
uint32_t flags = 0;
|
||||
|
||||
switch (get_impl()) {
|
||||
case None: { break; }
|
||||
@@ -662,72 +663,52 @@ void zygiskd_start(void) {
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("Flags: %d\n", flags);
|
||||
|
||||
ssize_t ret = write(client_fd, &flags, sizeof(flags));
|
||||
ssize_t ret = write_size_t(client_fd, flags);
|
||||
ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags));
|
||||
|
||||
uint32_t pid = getpid();
|
||||
|
||||
LOGI("Getting pid: %d\n", pid);
|
||||
|
||||
ret = write(client_fd, &pid, sizeof(pid));
|
||||
ret = write_uint32_t(client_fd, pid);
|
||||
ASSURE_SIZE_WRITE_BREAK("GetInfo", "pid", ret, sizeof(pid));
|
||||
|
||||
LOGI("Sent pid\n");
|
||||
|
||||
size_t modules_len = context.len;
|
||||
ret = write(client_fd, &modules_len, sizeof(modules_len));
|
||||
ret = write_size_t(client_fd, modules_len);
|
||||
|
||||
for (size_t i = 0; i < modules_len; i++) {
|
||||
write_string(client_fd, context.modules[i].name);
|
||||
}
|
||||
|
||||
LOGI("ZD++ GetInfo\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case ReadModules: {
|
||||
LOGI("Reading modules to stream\n");
|
||||
LOGI("ZD-- ReadModules\n");
|
||||
|
||||
size_t clen = context.len;
|
||||
ssize_t ret = write(client_fd, &clen, sizeof(clen));
|
||||
ssize_t ret = write_size_t(client_fd, clen);
|
||||
ASSURE_SIZE_WRITE_BREAK("ReadModules", "len", ret, sizeof(clen));
|
||||
|
||||
for (size_t i = 0; i < clen; i++) {
|
||||
LOGI("Hey, we're talking about: %zu, with name and lib_fd: %s, %d\n", i, context.modules[i].name, context.modules[i].lib_fd);
|
||||
|
||||
if (write_string(client_fd, context.modules[i].name) == -1) {
|
||||
LOGE("Failed writing module name\n");
|
||||
|
||||
break;
|
||||
if (write_string(client_fd, context.modules[i].name) == -1) break;
|
||||
if (gwrite_fd(client_fd, context.modules[i].lib_fd) == -1) break;
|
||||
}
|
||||
|
||||
if (send_fd(client_fd, context.modules[i].lib_fd) == -1) {
|
||||
LOGE("Failed sending lib fd\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("Finished reading modules to stream\n");
|
||||
LOGI("ZD++ ReadModules\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case RequestCompanionSocket: {
|
||||
LOGI("Requesting companion socket\n");
|
||||
LOGI("ZD-- RequestCompanionSocket\n");
|
||||
|
||||
size_t index_buf[1];
|
||||
ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf));
|
||||
ASSURE_SIZE_READ_BREAK("RequestCompanionSocket", "index", ret, sizeof(index_buf));
|
||||
|
||||
size_t index = index_buf[0];
|
||||
size_t index = 0;
|
||||
ssize_t ret = read_size_t(client_fd, &index);
|
||||
ASSURE_SIZE_READ_BREAK("RequestCompanionSocket", "index", ret, sizeof(index));
|
||||
|
||||
struct Module *module = &context.modules[index];
|
||||
|
||||
if (module->companion != -1) {
|
||||
LOGI("Companion for module `%s` already exists\n", module->name);
|
||||
|
||||
if (!check_unix_socket(module->companion, false)) {
|
||||
LOGE("Poll companion for module `%s` crashed\n", module->name);
|
||||
LOGE(" Poll companion for module \"%s\" crashed\n", module->name);
|
||||
|
||||
close(module->companion);
|
||||
module->companion = -1;
|
||||
@@ -735,74 +716,74 @@ void zygiskd_start(void) {
|
||||
}
|
||||
|
||||
if (module->companion == -1) {
|
||||
LOGI("Spawning companion for `%s`\n", module->name);
|
||||
module->companion = spawn_companion(argv, module->name, module->lib_fd);
|
||||
|
||||
module->companion = spawn_companion(module->name, module->lib_fd);
|
||||
|
||||
if (module->companion != -1) {
|
||||
LOGI("Spawned companion for `%s`\n", module->name);
|
||||
|
||||
/* INFO: Reversed params, may fix issues */
|
||||
if (send_fd(module->companion, client_fd) == -1) {
|
||||
LOGE("Failed sending companion fd\n");
|
||||
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
}
|
||||
if (module->companion > 0) {
|
||||
LOGI(" Spawned companion for \"%s\"\n", module->name);
|
||||
} else {
|
||||
if (module->companion == -2) {
|
||||
LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name);
|
||||
LOGE(" No companion spawned for \"%s\" because it has no entry.\n", module->name);
|
||||
} else {
|
||||
LOGI("Could not spawn companion for `%s` due to failures.\n", module->name);
|
||||
LOGE(" Failed to spawn companion for \"%s\": %s\n", module->name, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t response = 0;
|
||||
ret = write(client_fd, &response, sizeof(response));
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response));
|
||||
if (module->companion != -1) {
|
||||
if (gwrite_fd(module->companion, client_fd) == -1) {
|
||||
LOGE("Failed to send companion fd socket of module \"%s\"\n", module->name);
|
||||
|
||||
LOGI("Companion fd: %d\n", module->companion);
|
||||
ret = write_int(client_fd, 0);
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(int));
|
||||
}
|
||||
} else {
|
||||
ret = write_int(client_fd, 0);
|
||||
ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(int));
|
||||
}
|
||||
|
||||
LOGI("ZD++ RequestCompanionSocket\n");
|
||||
|
||||
break;
|
||||
}
|
||||
case GetModuleDir: {
|
||||
LOGI("Getting module directory\n");
|
||||
LOGI("ZD-- GetModuleDir\n");
|
||||
|
||||
size_t index_buf[1];
|
||||
ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf));
|
||||
ASSURE_SIZE_READ_BREAK("GetModuleDir", "index", ret, sizeof(index_buf));
|
||||
size_t index = 0;
|
||||
read_size_t(client_fd, &index);
|
||||
|
||||
size_t index = index_buf[0];
|
||||
char module_dir[PATH_MAX];
|
||||
snprintf(module_dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name);
|
||||
|
||||
LOGI("Index: %zu\n", index);
|
||||
|
||||
char dir[PATH_MAX];
|
||||
snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name);
|
||||
|
||||
LOGI("Module directory: %s\n", dir);
|
||||
/* INFO: Maybe not read only? */
|
||||
int dir_fd = open(dir, O_RDONLY);
|
||||
|
||||
LOGI("Module directory fd: %d\n", dir_fd);
|
||||
|
||||
if (send_fd(client_fd, dir_fd) == -1) {
|
||||
LOGE("Failed sending module directory fd\n");
|
||||
|
||||
close(dir_fd);
|
||||
int fd = open(module_dir, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
LOGE("Failed opening module directory \"%s\": %s\n", module_dir, strerror(errno));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LOGI("Sent module directory fd\n");
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) == -1) {
|
||||
LOGE("Failed getting module directory \"%s\" stats: %s\n", module_dir, strerror(errno));
|
||||
|
||||
close(fd);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (gwrite_fd(client_fd, fd) == -1) {
|
||||
LOGE("Failed sending module directory \"%s\" fd: %s\n", module_dir, strerror(errno));
|
||||
|
||||
close(fd);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LOGI("ZD++ GetModuleDir\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(client_fd);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef ZYGISKD_H
|
||||
#define ZYGISKD_H
|
||||
|
||||
void zygiskd_start(void);
|
||||
void zygiskd_start(char *restrict argv[]);
|
||||
|
||||
#endif /* ZYGISKD_H */
|
||||
|
||||
Reference in New Issue
Block a user