improve: port common code to C

This commit ports even more C++ code to C99, now, the codes available in the "common" folder.
This commit is contained in:
ThePedroo
2025-04-14 00:54:24 -03:00
parent 5b3d9c75fd
commit 1a3f497e1a
20 changed files with 633 additions and 857 deletions

365
loader/src/common/daemon.c Normal file
View File

@@ -0,0 +1,365 @@
// #include <unistd.h>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <dirent.h>
// #include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <linux/un.h>
#include "logging.h"
#include "socket_utils.h"
#include "daemon.h"
char daemon_path[PATH_MAX];
void rezygiskd_init(const char *path) {
snprintf(daemon_path, sizeof(daemon_path), "%s/%s", path, SOCKET_FILE_NAME);
}
void rezygiskd_get_path(char *buf, size_t buf_size) {
size_t fileless_daemon_path = strlen(daemon_path) - strlen("/") - strlen(SOCKET_FILE_NAME);
strncpy(buf, daemon_path, buf_size > fileless_daemon_path ? fileless_daemon_path : buf_size);
buf[fileless_daemon_path] = '\0';
}
int rezygiskd_connect(uint8_t retry) {
retry++;
int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fd == -1) {
PLOGE("socket create");
return -1;
}
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = { 0 }
};
/*
INFO: Application must assume that sun_path can hold _POSIX_PATH_MAX characters.
Sources:
- https://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/un.h.html
*/
strcpy(addr.sun_path, daemon_path);
socklen_t socklen = sizeof(addr);
while (--retry) {
int ret = connect(fd, (struct sockaddr *)&addr, socklen);
if (ret == 0) return fd;
if (retry) {
PLOGE("Retrying to connect to ReZygiskd, sleep 1s");
sleep(1);
}
}
close(fd);
return -1;
}
bool rezygiskd_ping() {
int fd = rezygiskd_connect(5);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return false;
}
write_uint8_t(fd, (uint8_t)PingHeartbeat);
close(fd);
return true;
}
uint32_t rezygiskd_get_process_flags(uid_t uid) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return 0;
}
write_uint8_t(fd, (uint8_t)GetProcessFlags);
write_uint32_t(fd, (uint32_t)uid);
uint32_t res = 0;
read_uint32_t(fd, &res);
close(fd);
return res;
}
void rezygiskd_get_info(struct rezygisk_info *info) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
info->running = false;
return;
}
info->running = true;
write_uint8_t(fd, (uint8_t)GetInfo);
uint32_t flags = 0;
read_uint32_t(fd, &flags);
if (flags & (1 << 27)) info->root_impl = ROOT_IMPL_APATCH;
else if (flags & (1 << 29)) info->root_impl = ROOT_IMPL_KERNELSU;
else if (flags & (1 << 30)) info->root_impl = ROOT_IMPL_MAGISK;
else info->root_impl = ROOT_IMPL_NONE;
read_uint32_t(fd, (uint32_t *)&info->pid);
read_size_t(fd, &info->modules->modules_count);
if (info->modules->modules_count == 0) {
info->modules->modules = NULL;
close(fd);
return;
}
info->modules->modules = (char **)malloc(sizeof(char *) * info->modules->modules_count);
if (info->modules->modules == NULL) {
PLOGE("allocating modules name memory");
free(info->modules);
info->modules = NULL;
info->modules->modules_count = 0;
close(fd);
return;
}
for (size_t i = 0; i < info->modules->modules_count; i++) {
char *module_name = read_string(fd);
if (module_name == NULL) {
PLOGE("reading module name");
info->modules->modules_count = i;
free_rezygisk_info(info);
info->modules = NULL;
info->modules->modules_count = 0;
close(fd);
return;
}
char module_path[PATH_MAX];
snprintf(module_path, sizeof(module_path), "/data/adb/modules/%s/module.prop", module_name);
FILE *module_prop = fopen(module_path, "r");
if (!module_prop) {
PLOGE("failed to open module prop file %s", module_path);
info->modules->modules_count = i;
free_rezygisk_info(info);
info->modules = NULL;
info->modules->modules_count = 0;
close(fd);
return;
}
char line[1024];
while (fgets(line, sizeof(line), module_prop) != NULL) {
if (strncmp(line, "name=", strlen("name=")) != 0) continue;
info->modules->modules[i] = strndup(line + 5, strlen(line) - 6);
break;
}
fclose(module_prop);
}
close(fd);
}
void free_rezygisk_info(struct rezygisk_info *info) {
if (info->modules->modules) {
for (size_t i = 0; i < info->modules->modules_count; i++) {
free(info->modules->modules[i]);
}
free(info->modules->modules);
}
free(info->modules);
}
bool rezygiskd_read_modules(struct zygisk_modules *modules) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return false;
}
write_uint8_t(fd, (uint8_t)ReadModules);
size_t len = 0;
read_size_t(fd, &len);
modules->modules = malloc(len * sizeof(char *));
if (!modules->modules) {
PLOGE("allocating modules name memory");
close(fd);
return false;
}
modules->modules_count = len;
for (size_t i = 0; i < len; i++) {
char *lib_path = read_string(fd);
if (!lib_path) {
PLOGE("reading module lib_path");
close(fd);
return false;
}
modules->modules[i] = lib_path;
}
close(fd);
return true;
}
void free_modules(struct zygisk_modules *modules) {
if (modules->modules) {
for (size_t i = 0; i < modules->modules_count; i++) {
free(modules->modules[i]);
}
free(modules->modules);
}
}
int rezygiskd_connect_companion(size_t index) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return -1;
}
write_uint8_t(fd, (uint8_t)RequestCompanionSocket);
write_size_t(fd, index);
uint8_t res = 0;
read_uint8_t(fd, &res);
if (res == 1) return fd;
else {
close(fd);
return -1;
}
}
int rezygiskd_get_module_dir(size_t index) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return -1;
}
write_uint8_t(fd, (uint8_t)GetModuleDir);
write_size_t(fd, index);
int dirfd = read_fd(fd);
close(fd);
return dirfd;
}
void rezygiskd_zygote_restart() {
int fd = rezygiskd_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");
return;
}
if (!write_uint8_t(fd, (uint8_t)ZygoteRestart))
PLOGE("Failed to request ZygoteRestart");
close(fd);
}
void rezygiskd_system_server_started() {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("Failed to report system server started");
return;
}
if (!write_uint8_t(fd, (uint8_t)SystemServerStarted))
PLOGE("Failed to request SystemServerStarted");
close(fd);
}
bool rezygiskd_update_mns(enum mount_namespace_state nms_state, char *buf, size_t buf_size) {
int fd = rezygiskd_connect(1);
if (fd == -1) {
PLOGE("connection to ReZygiskd");
return false;
}
write_uint8_t(fd, (uint8_t)UpdateMountNamespace);
write_uint32_t(fd, (uint32_t)getpid());
write_uint8_t(fd, (uint8_t)nms_state);
uint32_t target_pid = 0;
read_uint32_t(fd, &target_pid);
if (target_pid == 0) {
close(fd);
return false;
}
int target_fd = read_fd(fd);
if (target_fd == -1) {
close(fd);
return false;
}
snprintf(buf, buf_size, "/proc/%u/fd/%u", target_pid, target_fd);
close(fd);
return true;
}

View File

@@ -1,279 +0,0 @@
#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 "socket_utils.h"
namespace zygiskd {
static std::string TMP_PATH;
void Init(const char *path) {
TMP_PATH = path;
}
std::string GetTmpPath() {
return TMP_PATH;
}
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 }
};
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, (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() {
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;
}
uint32_t GetProcessFlags(uid_t uid) {
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);
uint32_t res = socket_utils::read_u32(fd);
close(fd);
return res;
}
std::vector<ModuleInfo> ReadModules() {
std::vector<ModuleInfo> modules;
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++) {
std::string lib_path = socket_utils::read_string(fd);
std::string name = socket_utils::read_string(fd);
modules.emplace_back(lib_path, name);
}
close(fd);
return modules;
}
int ConnectCompanion(size_t index) {
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);
uint8_t res = socket_utils::read_u8(fd);
if (res == 1) return fd;
else {
close(fd);
return -1;
}
}
int GetModuleDir(size_t index) {
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);
int nfd = socket_utils::recv_fd(fd);
close(fd);
return nfd;
}
void ZygoteRestart() {
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");
return;
}
if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart))
PLOGE("Failed to request ZygoteRestart");
close(fd);
}
void 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) {
/* TODO: Optimize and avoid re-connect twice here */
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);
if (flags & (1 << 27)) {
info->root_impl = ZYGOTE_ROOT_IMPL_APATCH;
} else if (flags & (1 << 29)) {
info->root_impl = ZYGOTE_ROOT_IMPL_KERNELSU;
} else if (flags & (1 << 30)) {
info->root_impl = ZYGOTE_ROOT_IMPL_MAGISK;
} else {
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;
close(fd);
return;
}
info->modules->modules_count = socket_utils::read_usize(fd);
if (info->modules->modules_count == 0) {
info->modules->modules = NULL;
close(fd);
return;
}
info->modules->modules = (char **)malloc(sizeof(char *) * info->modules->modules_count);
if (info->modules->modules == NULL) {
free(info->modules);
info->modules = NULL;
info->modules->modules_count = 0;
close(fd);
return;
}
for (size_t i = 0; i < info->modules->modules_count; i++) {
/* INFO by ThePedroo: Ugly solution to read with std::string existance (temporary) */
std::string name = socket_utils::read_string(fd);
char module_path[PATH_MAX];
snprintf(module_path, sizeof(module_path), "/data/adb/modules/%s/module.prop", name.c_str());
FILE *module_prop = fopen(module_path, "r");
if (module_prop == NULL) {
info->modules->modules[i] = strdup(name.c_str());
} else {
char line[1024];
while (fgets(line, sizeof(line), module_prop) != NULL) {
if (strncmp(line, "name=", 5) == 0) {
info->modules->modules[i] = strndup(line + 5, strlen(line) - 6);
break;
}
}
fclose(module_prop);
}
}
close(fd);
} else info->running = false;
}
std::string UpdateMountNamespace(enum mount_namespace_state nms_state) {
int fd = Connect(1);
if (fd == -1) {
PLOGE("UpdateMountNamespace");
return "";
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::UpdateMountNamespace);
socket_utils::write_u32(fd, getpid());
socket_utils::write_u8(fd, (uint8_t)nms_state);
uint32_t target_pid = socket_utils::read_u32(fd);
int target_fd = 0;
if (target_pid == 0) goto error;
target_fd = (int)socket_utils::read_u32(fd);
if (target_fd == 0) goto error;
close(fd);
return "/proc/" + std::to_string(target_pid) + "/fd/" + std::to_string(target_fd);
error:
close(fd);
return "";
}
}

View File

@@ -1,119 +0,0 @@
#include <sys/sysmacros.h>
#include "files.hpp"
#include "misc.hpp"
using namespace std::string_view_literals;
void file_readline(bool trim, FILE *fp, const std::function<bool(std::string_view)> &fn) {
size_t len = 1024;
char *buf = (char *) malloc(len);
char *start;
ssize_t read;
while ((read = getline(&buf, &len, fp)) >= 0) {
start = buf;
if (trim) {
while (read && "\n\r "sv.find(buf[read - 1]) != std::string::npos)
--read;
buf[read] = '\0';
while (*start == ' ')
++start;
}
if (!fn(start))
break;
}
free(buf);
}
void file_readline(const char *file, const std::function<bool(std::string_view)> &fn) {
FILE *fp = fopen(file, "re");
if (!fp) {
PLOGE("Failed to open file %s", file);
return;
}
file_readline(false, fp, fn);
fclose(fp);
}
std::vector<mount_info> parse_mount_info(const char *pid) {
char buf[PATH_MAX] = {};
snprintf(buf, sizeof(buf), "/proc/%s/mountinfo", pid);
std::vector<mount_info> result;
file_readline(buf, [&result](std::string_view line) -> bool {
int root_start = 0, root_end = 0;
int target_start = 0, target_end = 0;
int vfs_option_start = 0, vfs_option_end = 0;
int type_start = 0, type_end = 0;
int source_start = 0, source_end = 0;
int fs_option_start = 0, fs_option_end = 0;
int optional_start = 0, optional_end = 0;
unsigned int id, parent, maj, min;
sscanf(line.data(),
"%u " // (1) id
"%u " // (2) parent
"%u:%u " // (3) maj:min
"%n%*s%n " // (4) mountroot
"%n%*s%n " // (5) target
"%n%*s%n" // (6) vfs options (fs-independent)
"%n%*[^-]%n - " // (7) optional fields
"%n%*s%n " // (8) FS type
"%n%*s%n " // (9) source
"%n%*s%n", // (10) fs options (fs specific)
&id, &parent, &maj, &min, &root_start, &root_end, &target_start,
&target_end, &vfs_option_start, &vfs_option_end,
&optional_start, &optional_end, &type_start, &type_end,
&source_start, &source_end, &fs_option_start, &fs_option_end);
auto root = line.substr(root_start, root_end - root_start);
auto target = line.substr(target_start, target_end - target_start);
auto vfs_option =
line.substr(vfs_option_start, vfs_option_end - vfs_option_start);
++optional_start;
--optional_end;
auto optional = line.substr(
optional_start,
optional_end - optional_start > 0 ? optional_end - optional_start : 0);
auto type = line.substr(type_start, type_end - type_start);
auto source = line.substr(source_start, source_end - source_start);
auto fs_option =
line.substr(fs_option_start, fs_option_end - fs_option_start);
unsigned int shared = 0;
unsigned int master = 0;
unsigned int propagate_from = 0;
if (auto pos = optional.find("shared:"); pos != std::string_view::npos) {
shared = parse_int(optional.substr(pos + 7));
}
if (auto pos = optional.find("master:"); pos != std::string_view::npos) {
master = parse_int(optional.substr(pos + 7));
}
if (auto pos = optional.find("propagate_from:");
pos != std::string_view::npos) {
propagate_from = parse_int(optional.substr(pos + 15));
}
result.emplace_back(mount_info {
.id = id,
.parent = parent,
.device = static_cast<dev_t>(makedev(maj, min)),
.root {root},
.target {target},
.vfs_option {vfs_option},
.optional {
.shared = shared,
.master = master,
.propagate_from = propagate_from,
},
.type {type},
.source {source},
.fs_option {fs_option},
});
return true;
});
return result;
}

14
loader/src/common/misc.c Normal file
View File

@@ -0,0 +1,14 @@
int parse_int(const char *str) {
int val = 0;
char *c = (char *)str;
while (*c) {
if (*c > '9' || *c < '0')
return -1;
val = val * 10 + *c - '0';
c++;
}
return val;
}

View File

@@ -1,49 +0,0 @@
#include "misc.hpp"
int new_daemon_thread(thread_entry entry, void *arg) {
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
errno = pthread_create(&thread, &attr, entry, arg);
if (errno) {
PLOGE("pthread_create");
}
return errno;
}
int parse_int(std::string_view s) {
int val = 0;
for (char c : s) {
if (!c) break;
if (c > '9' || c < '0')
return -1;
val = val * 10 + c - '0';
}
return val;
}
std::list<std::string> split_str(std::string_view s, std::string_view delimiter) {
std::list<std::string> ret;
size_t pos = 0;
while (pos < s.size()) {
auto next = s.find(delimiter, pos);
if (next == std::string_view::npos) {
ret.emplace_back(s.substr(pos));
break;
}
ret.emplace_back(s.substr(pos, next - pos));
pos = next + delimiter.size();
}
return ret;
}
std::string join_str(const std::list<std::string>& list, std::string_view delimiter) {
std::string ret;
for (auto& s : list) {
if (!ret.empty())
ret += delimiter;
ret += s;
}
return ret;
}

View File

@@ -0,0 +1,95 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#include "logging.h"
#include "socket_utils.h"
/* TODO: Standardize how to log errors */
int read_fd(int fd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];
int cnt = 1;
struct iovec iov = {
.iov_base = &cnt,
.iov_len = sizeof(cnt)
};
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
.msg_controllen = sizeof(cmsgbuf)
};
ssize_t ret = recvmsg(fd, &msg, MSG_WAITALL);
if (ret == -1) {
PLOGE("recvmsg");
return -1;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
PLOGE("CMSG_FIRSTHDR");
return -1;
}
int sendfd;
memcpy(&sendfd, CMSG_DATA(cmsg), sizeof(int));
return sendfd;
}
char *read_string(int fd) {
size_t str_len = 0;
ssize_t read_bytes = read(fd, &str_len, 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 NULL;
}
char *buf = malloc(str_len + 1);
if (buf == NULL) {
PLOGE("allocate memory for string");
return NULL;
}
read_bytes = read(fd, buf, str_len);
if (read_bytes != (ssize_t)str_len) {
LOGE("Failed to read string: Promised bytes doesn't exist (%zd != %zu).\n", read_bytes, str_len);
free(buf);
return NULL;
}
if (str_len > 0) buf[str_len] = '\0';
return buf;
}
#define write_func(type) \
ssize_t write_## type(int fd, type val) { \
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(uint8_t)
read_func(uint8_t)
write_func(uint32_t)
read_func(uint32_t)
write_func(size_t)
read_func(size_t)

View File

@@ -1,137 +0,0 @@
#include <cstddef>
#include <sys/socket.h>
#include <unistd.h>
#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;
do {
ret = read(fd, (std::byte*) buf + read_sz, count - read_sz);
if (ret < 0) {
if (errno == EINTR) continue;
PLOGE("read");
return ret;
}
read_sz += ret;
} while (read_sz != count && ret != 0);
if (read_sz != count) {
PLOGE("read (%zu != %zu)", count, read_sz);
}
return read_sz;
}
size_t xwrite(int fd, const void* buf, size_t count) {
size_t write_sz = 0;
ssize_t ret;
do {
ret = write(fd, (std::byte*) buf + write_sz, count - write_sz);
if (ret < 0) {
if (errno == EINTR) continue;
PLOGE("write");
return write_sz;
}
write_sz += ret;
} while (write_sz != count && ret != 0);
if (write_sz != count) {
PLOGE("write (%zu != %zu)", count, write_sz);
}
return write_sz;
}
ssize_t xrecvmsg(int sockfd, struct msghdr* msg, int flags) {
int rec = recvmsg(sockfd, msg, flags);
if (rec < 0) PLOGE("recvmsg");
return rec;
}
template<typename T>
inline T read_exact_or(int fd, T fail) {
T res;
return sizeof(T) == xread(fd, &res, sizeof(T)) ? res : fail;
}
template<typename T>
inline bool write_exact(int fd, T val) {
return sizeof(T) == xwrite(fd, &val, sizeof(T));
}
uint8_t read_u8(int fd) {
return read_exact_or<uint8_t>(fd, 0);
}
uint32_t read_u32(int fd) {
return read_exact_or<uint32_t>(fd, 0);
}
size_t read_usize(int fd) {
return read_exact_or<size_t>(fd, 0);
}
bool write_usize(int fd, size_t val) {
return write_exact<size_t>(fd, val);
}
std::string read_string(int fd) {
size_t len = read_usize(fd);
char buf[len + 1];
xread(fd, buf, len);
buf[len] = '\0';
return buf;
}
bool write_u8(int fd, uint8_t val) {
return write_exact<uint8_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;
}
return CMSG_DATA(cmsg);
}
int recv_fd(int sockfd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];
void* data = recv_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), 1);
if (data == nullptr) return -1;
int result;
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());
}
}

View File

@@ -1,113 +1,85 @@
#pragma once #ifndef DAEMON_H
#define DAEMON_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <string_view>
#include <string>
#include <unistd.h> #include <unistd.h>
#include <vector>
#if defined(__LP64__) #ifdef __LP64__
# define LP_SELECT(lp32, lp64) lp64 #define LP_SELECT(lp32, lp64) lp64
#else #else
# define LP_SELECT(lp32, lp64) lp32 #define LP_SELECT(lp32, lp64) lp32
#endif #endif
constexpr auto kCPSocketName = "/" LP_SELECT("cp32", "cp64") ".sock"; #define SOCKET_FILE_NAME LP_SELECT("cp32", "cp64") ".sock"
class UniqueFd { enum rezygiskd_actions {
using Fd = int; PingHeartbeat,
public: GetProcessFlags,
UniqueFd() = default; GetInfo,
ReadModules,
UniqueFd(Fd fd) : fd_(fd) {} RequestCompanionSocket,
GetModuleDir,
~UniqueFd() { if (fd_ >= 0) close(fd_); } ZygoteRestart,
SystemServerStarted,
// Disallow copy UpdateMountNamespace
UniqueFd(const UniqueFd&) = delete;
UniqueFd& operator=(const UniqueFd&) = delete;
// Allow move
UniqueFd(UniqueFd&& other) { std::swap(fd_, other.fd_); }
UniqueFd& operator=(UniqueFd&& other) {
std::swap(fd_, other.fd_);
return *this;
}
// Implict cast to Fd
operator const Fd&() const { return fd_; }
private:
Fd fd_ = -1;
}; };
struct zygote_modules { struct zygisk_modules {
char **modules; char **modules;
size_t modules_count; size_t modules_count;
}; };
enum zygote_root_impl { enum root_impl {
ZYGOTE_ROOT_IMPL_NONE, ROOT_IMPL_NONE,
ZYGOTE_ROOT_IMPL_APATCH, ROOT_IMPL_APATCH,
ZYGOTE_ROOT_IMPL_KERNELSU, ROOT_IMPL_KERNELSU,
ZYGOTE_ROOT_IMPL_MAGISK ROOT_IMPL_MAGISK
}; };
struct zygote_info { struct rezygisk_info {
struct zygote_modules *modules; struct zygisk_modules *modules;
enum zygote_root_impl root_impl; enum root_impl root_impl;
pid_t pid; pid_t pid;
bool running; bool running;
}; };
enum mount_namespace_state { enum mount_namespace_state {
Clean, Clean,
Rooted, Rooted,
Module Module
}; };
namespace zygiskd { void rezygiskd_init(const char *path);
struct ModuleInfo { void rezygiskd_get_path(char *buf, size_t buf_size);
std::string path;
/* TODO: Perhaps we can also remove this and just send paths? */
std::string name;
inline explicit ModuleInfo(std::string path, std::string name) : path(path), name(name) {} int rezygiskd_connect(uint8_t retry);
};
enum class SocketAction { bool rezygiskd_ping();
PingHeartBeat,
GetProcessFlags,
GetInfo,
ReadModules,
RequestCompanionSocket,
GetModuleDir,
ZygoteRestart,
SystemServerStarted,
UpdateMountNamespace
};
void Init(const char *path); uint32_t rezygiskd_get_process_flags(uid_t uid);
std::string GetTmpPath(); void rezygiskd_get_info(struct rezygisk_info *info);
bool PingHeartbeat(); void free_rezygisk_info(struct rezygisk_info *info);
std::vector<ModuleInfo> ReadModules(); bool rezygiskd_read_modules(struct zygisk_modules *modules);
void free_modules(struct zygisk_modules *modules);
uint32_t GetProcessFlags(uid_t uid); int rezygiskd_connect_companion(size_t index);
int ConnectCompanion(size_t index); int rezygiskd_get_module_dir(size_t index);
int GetModuleDir(size_t index); void rezygiskd_zygote_restart();
void ZygoteRestart(); void rezygiskd_system_server_started();
void SystemServerStarted(); bool rezygiskd_update_mns(enum mount_namespace_state nms_state, char *buf, size_t buf_size);
void GetInfo(struct zygote_info *info); #ifdef __cplusplus
std::string UpdateMountNamespace(enum mount_namespace_state mns_state);
} }
#endif /* __cplusplus */
#endif /* DAEMON_H */

View File

@@ -6,8 +6,6 @@
#include <linux/elf.h> #include <linux/elf.h>
#include <sys/types.h> #include <sys/types.h>
#define restrict /* INFO: Temporary measure */
#define SHT_GNU_HASH 0x6ffffff6 #define SHT_GNU_HASH 0x6ffffff6
struct symtabs { struct symtabs {

View File

@@ -1,24 +0,0 @@
#include <dirent.h>
#include <functional>
#include <string>
#include <vector>
#include <unistd.h>
struct mount_info {
unsigned int id;
unsigned int parent;
dev_t device;
std::string root;
std::string target;
std::string vfs_option;
struct {
unsigned int shared;
unsigned int master;
unsigned int propagate_from;
} optional;
std::string type;
std::string source;
std::string fs_option;
};
std::vector<mount_info> parse_mount_info(const char *pid);

17
loader/src/include/misc.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef MISC_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Bionic's atoi runs through strtol().
* Use our own implementation for faster conversion.
*/
int parse_int(const char *str);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MISC_H */

View File

@@ -1,98 +0,0 @@
#pragma once
#include <list>
#include <memory>
#include <pthread.h>
#include <string>
#include <string_view>
#include "logging.h"
#define DISALLOW_COPY_AND_MOVE(clazz) \
clazz(const clazz &) = delete; \
clazz(clazz &&) = delete;
class mutex_guard {
DISALLOW_COPY_AND_MOVE(mutex_guard)
public:
explicit mutex_guard(pthread_mutex_t &m): mutex(&m) {
pthread_mutex_lock(mutex);
}
void unlock() {
pthread_mutex_unlock(mutex);
mutex = nullptr;
}
~mutex_guard() {
if (mutex) pthread_mutex_unlock(mutex);
}
private:
pthread_mutex_t *mutex;
};
using thread_entry = void *(*)(void *);
int new_daemon_thread(thread_entry entry, void *arg);
static inline bool str_contains(std::string_view s, std::string_view ss) {
return s.find(ss) != std::string_view::npos;
}
template<typename T, typename Impl>
class stateless_allocator {
public:
using value_type = T;
T *allocate(size_t num) { return static_cast<T*>(Impl::allocate(sizeof(T) * num)); }
void deallocate(T *ptr, size_t num) { Impl::deallocate(ptr, sizeof(T) * num); }
stateless_allocator() = default;
stateless_allocator(const stateless_allocator&) = default;
stateless_allocator(stateless_allocator&&) = default;
template <typename U>
stateless_allocator(const stateless_allocator<U, Impl>&) {}
bool operator==(const stateless_allocator&) { return true; }
bool operator!=(const stateless_allocator&) { return false; }
};
template <typename T>
class reversed_container {
public:
reversed_container(T &base) : base(base) {}
decltype(std::declval<T>().rbegin()) begin() { return base.rbegin(); }
decltype(std::declval<T>().crbegin()) begin() const { return base.crbegin(); }
decltype(std::declval<T>().crbegin()) cbegin() const { return base.crbegin(); }
decltype(std::declval<T>().rend()) end() { return base.rend(); }
decltype(std::declval<T>().crend()) end() const { return base.crend(); }
decltype(std::declval<T>().crend()) cend() const { return base.crend(); }
private:
T &base;
};
template <typename T>
reversed_container<T> reversed(T &base) {
return reversed_container<T>(base);
}
template<class T>
static inline void default_new(T *&p) { p = new T(); }
template<class T>
static inline void default_new(std::unique_ptr<T> &p) { p.reset(new T()); }
struct StringCmp {
using is_transparent = void;
bool operator()(std::string_view a, std::string_view b) const { return a < b; }
};
/*
* Bionic's atoi runs through strtol().
* Use our own implementation for faster conversion.
*/
int parse_int(std::string_view s);
std::list<std::string> split_str(std::string_view s, std::string_view delimiter);
std::string join_str(const std::list<std::string>& list, std::string_view delimiter);
template <typename T>
static inline T align_to(T v, int a) {
static_assert(std::is_integral<T>::value);
return (v + a - 1) / a * a;
}

View File

@@ -1,31 +1,25 @@
#pragma once #ifndef SOCKET_UTILS_H
#define SOCKET_UTILS_H
#include <string> #include <stdint.h>
#include <string_view>
#include "logging.h" int read_fd(int fd);
char *read_string(int fd);
namespace socket_utils { #define write_func_def(type) \
ssize_t write_## type(int fd, type val)
ssize_t xread(int fd, void *buf, size_t count); #define read_func_def(type) \
ssize_t read_## type(int fd, type *val)
size_t xwrite(int fd, const void *buf, size_t count); write_func_def(uint8_t);
read_func_def(uint8_t);
uint8_t read_u8(int fd); write_func_def(uint32_t);
read_func_def(uint32_t);
uint32_t read_u32(int fd); write_func_def(size_t);
read_func_def(size_t);
size_t read_usize(int fd); #endif /* SOCKET_UTILS_H */
std::string read_string(int fd);
bool write_u8(int fd, uint8_t val);
bool write_u32(int fd, uint32_t val);
int recv_fd(int fd);
bool write_usize(int fd, size_t val);
bool write_string(int fd, std::string_view str);
}

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "logging.h"
#include "jni_helper.hpp" #include "jni_helper.hpp"
template <typename T> template <typename T>

View File

@@ -12,10 +12,11 @@ void entry(void* addr, size_t size, const char* path) {
LOGD("Zygisk library injected, version %s", ZKSU_VERSION); LOGD("Zygisk library injected, version %s", ZKSU_VERSION);
start_addr = addr; start_addr = addr;
block_size = size; block_size = size;
zygiskd::Init(path); rezygiskd_init(path);
if (!zygiskd::PingHeartbeat()) { if (!rezygiskd_ping()) {
LOGE("Zygisk daemon is not running"); LOGE("Zygisk daemon is not running");
return; return;
} }

View File

@@ -5,6 +5,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include <array> #include <array>
#include <vector>
#include <lsplt.hpp> #include <lsplt.hpp>
@@ -16,12 +17,12 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h>
#include "daemon.h" #include "daemon.h"
#include "zygisk.hpp" #include "zygisk.hpp"
#include "module.hpp" #include "module.hpp"
#include "files.hpp" #include "misc.h"
#include "misc.hpp"
#include "solist.h" #include "solist.h"
@@ -121,7 +122,7 @@ struct ZygiskContext {
// Global variables // Global variables
vector<tuple<dev_t, ino_t, const char *, void **>> *plt_hook_list; vector<tuple<dev_t, ino_t, const char *, void **>> *plt_hook_list;
map<string, vector<JNINativeMethod>, StringCmp> *jni_hook_list; map<string, vector<JNINativeMethod>> *jni_hook_list;
bool should_unmap_zygisk = false; bool should_unmap_zygisk = false;
std::vector<lsplt::MapInfo> cached_map_infos = {}; std::vector<lsplt::MapInfo> cached_map_infos = {};
@@ -139,8 +140,8 @@ DCL_HOOK_FUNC(int, fork) {
} }
bool update_mnt_ns(enum mount_namespace_state mns_state, bool dry_run) { bool update_mnt_ns(enum mount_namespace_state mns_state, bool dry_run) {
std::string ns_path = zygiskd::UpdateMountNamespace(mns_state); char ns_path[PATH_MAX];
if (ns_path.empty()) { if (rezygiskd_update_mns(mns_state, ns_path, sizeof(ns_path)) == false) {
PLOGE("Failed to update mount namespace"); PLOGE("Failed to update mount namespace");
return false; return false;
@@ -148,16 +149,16 @@ bool update_mnt_ns(enum mount_namespace_state mns_state, bool dry_run) {
if (dry_run) return true; if (dry_run) return true;
int updated_ns = open(ns_path.data(), O_RDONLY); int updated_ns = open(ns_path, O_RDONLY);
if (updated_ns == -1) { if (updated_ns == -1) {
PLOGE("Failed to open mount namespace [%s]", ns_path.data()); PLOGE("Failed to open mount namespace [%s]", ns_path);
return false; return false;
} }
LOGD("set mount namespace to [%s] fd=[%d]\n", ns_path.data(), updated_ns); LOGD("set mount namespace to [%s] fd=[%d]\n", ns_path, updated_ns);
if (setns(updated_ns, CLONE_NEWNS) == -1) { if (setns(updated_ns, CLONE_NEWNS) == -1) {
PLOGE("Failed to set mount namespace [%s]", ns_path.data()); PLOGE("Failed to set mount namespace [%s]", ns_path);
close(updated_ns); close(updated_ns);
return false; return false;
@@ -180,6 +181,8 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
update_mnt_ns(Rooted, false); update_mnt_ns(Rooted, false);
} else if (!(g_ctx->flags[DO_REVERT_UNMOUNT])) { } else if (!(g_ctx->flags[DO_REVERT_UNMOUNT])) {
update_mnt_ns(Module, false); update_mnt_ns(Module, false);
} else {
LOGI("Process [%s] is on denylist, skipping unmount", g_ctx->process);
} }
old_unshare(CLONE_NEWNS); old_unshare(CLONE_NEWNS);
@@ -389,8 +392,9 @@ void ZygiskContext::plt_hook_register(const char *regex, const char *symbol, voi
regex_t re; regex_t re;
if (regcomp(&re, regex, REG_NOSUB) != 0) if (regcomp(&re, regex, REG_NOSUB) != 0)
return; return;
mutex_guard lock(hook_info_lock); pthread_mutex_lock(&hook_info_lock);
register_info.emplace_back(RegisterInfo{re, symbol, fn, backup}); register_info.emplace_back(RegisterInfo{re, symbol, fn, backup});
pthread_mutex_unlock(&hook_info_lock);
} }
void ZygiskContext::plt_hook_exclude(const char *regex, const char *symbol) { void ZygiskContext::plt_hook_exclude(const char *regex, const char *symbol) {
@@ -398,8 +402,9 @@ void ZygiskContext::plt_hook_exclude(const char *regex, const char *symbol) {
regex_t re; regex_t re;
if (regcomp(&re, regex, REG_NOSUB) != 0) if (regcomp(&re, regex, REG_NOSUB) != 0)
return; return;
mutex_guard lock(hook_info_lock); pthread_mutex_lock(&hook_info_lock);
ignore_info.emplace_back(IgnoreInfo{re, symbol ?: ""}); ignore_info.emplace_back(IgnoreInfo{re, symbol ?: ""});
pthread_mutex_unlock(&hook_info_lock);
} }
void ZygiskContext::plt_hook_process_regex() { void ZygiskContext::plt_hook_process_regex() {
@@ -428,11 +433,13 @@ void ZygiskContext::plt_hook_process_regex() {
bool ZygiskContext::plt_hook_commit() { bool ZygiskContext::plt_hook_commit() {
{ {
mutex_guard lock(hook_info_lock); pthread_mutex_lock(&hook_info_lock);
plt_hook_process_regex(); plt_hook_process_regex();
register_info.clear(); register_info.clear();
ignore_info.clear(); ignore_info.clear();
pthread_mutex_unlock(&hook_info_lock);
} }
return lsplt::CommitHook(cached_map_infos); return lsplt::CommitHook(cached_map_infos);
} }
@@ -454,12 +461,12 @@ bool ZygiskModule::valid() const {
/* Zygisksu changed: Use own zygiskd */ /* Zygisksu changed: Use own zygiskd */
int ZygiskModule::connectCompanion() const { int ZygiskModule::connectCompanion() const {
return zygiskd::ConnectCompanion(id); return rezygiskd_connect_companion(id);
} }
/* Zygisksu changed: Use own zygiskd */ /* Zygisksu changed: Use own zygiskd */
int ZygiskModule::getModuleDir() const { int ZygiskModule::getModuleDir() const {
return zygiskd::GetModuleDir(id); return rezygiskd_get_module_dir(id);
} }
void ZygiskModule::setOption(zygisk::Option opt) { void ZygiskModule::setOption(zygisk::Option opt) {
@@ -596,21 +603,26 @@ void ZygiskContext::fork_post() {
/* Zygisksu changed: Load module fds */ /* Zygisksu changed: Load module fds */
void ZygiskContext::run_modules_pre() { void ZygiskContext::run_modules_pre() {
auto ms = zygiskd::ReadModules(); struct zygisk_modules ms;
auto size = ms.size(); if (rezygiskd_read_modules(&ms) == false) {
for (size_t i = 0; i < size; i++) { LOGE("Failed to read modules from zygiskd");
auto &m = ms[i];
void *handle = dlopen(m.path.c_str(), RTLD_NOW); return;
}
for (size_t i = 0; i < ms.modules_count; i++) {
char *lib_path = ms.modules[i];
void *handle = dlopen(lib_path, RTLD_NOW);
if (!handle) { if (!handle) {
LOGE("Failed to load module [%s]: %s", m.path.c_str(), dlerror()); LOGE("Failed to load module [%s]: %s", lib_path, dlerror());
continue; continue;
} }
void *entry = dlsym(handle, "zygisk_module_entry"); void *entry = dlsym(handle, "zygisk_module_entry");
if (!entry) { if (!entry) {
LOGE("Failed to find entry point in module [%s]: %s", m.path.c_str(), dlerror()); LOGE("Failed to find entry point in module [%s]: %s", lib_path, dlerror());
dlclose(handle); dlclose(handle);
@@ -620,6 +632,8 @@ void ZygiskContext::run_modules_pre() {
modules.emplace_back(i, handle, entry); modules.emplace_back(i, handle, entry);
} }
free_modules(&ms);
for (auto &m : modules) { for (auto &m : modules) {
m.onLoad(env); m.onLoad(env);
if (flags[APP_SPECIALIZE]) m.preAppSpecialize(args.app); if (flags[APP_SPECIALIZE]) m.preAppSpecialize(args.app);
@@ -648,7 +662,7 @@ void ZygiskContext::run_modules_post() {
void ZygiskContext::app_specialize_pre() { void ZygiskContext::app_specialize_pre() {
flags[APP_SPECIALIZE] = true; flags[APP_SPECIALIZE] = true;
info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid); info_flags = rezygiskd_get_process_flags(g_ctx->args.app->uid);
if (info_flags & PROCESS_IS_FIRST_STARTED) { if (info_flags & PROCESS_IS_FIRST_STARTED) {
update_mnt_ns(Clean, true); update_mnt_ns(Clean, true);
} }
@@ -707,7 +721,7 @@ void ZygiskContext::nativeForkSystemServer_pre() {
fork_pre(); fork_pre();
if (is_child()) { if (is_child()) {
run_modules_pre(); run_modules_pre();
zygiskd::SystemServerStarted(); rezygiskd_system_server_started();
} }
sanitize_fds(); sanitize_fds();
@@ -834,14 +848,11 @@ void clean_trace(const char* path, size_t load, size_t unload, bool spoof_maps)
} }
void hook_functions() { void hook_functions() {
default_new(plt_hook_list); plt_hook_list = new vector<tuple<dev_t, ino_t, const char *, void **>>();
default_new(jni_hook_list); jni_hook_list = new map<string, vector<JNINativeMethod>>();
ino_t android_runtime_inode = 0; ino_t android_runtime_inode = 0;
dev_t android_runtime_dev = 0; dev_t android_runtime_dev = 0;
/* TODO by ThePedroo: Implement injection via native bridge */
// ino_t native_bridge_inode = 0;
// dev_t native_bridge_dev = 0;
cached_map_infos = lsplt::MapInfo::Scan(); cached_map_infos = lsplt::MapInfo::Scan();
for (auto &map : cached_map_infos) { for (auto &map : cached_map_infos) {

View File

@@ -1,7 +1,6 @@
#ifndef SOLIST_H #ifndef SOLIST_H
#define SOLIST_H #define SOLIST_H
/* INFO: Temporary */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@@ -5,7 +5,7 @@
#include "daemon.h" #include "daemon.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
zygiskd::Init("/data/adb/rezygisk"); rezygiskd_init("/data/adb/rezygisk");
printf("The ReZygisk Tracer %s\n\n", ZKSU_VERSION); printf("The ReZygisk Tracer %s\n\n", ZKSU_VERSION);
@@ -16,7 +16,7 @@ int main(int argc, char **argv) {
return 0; return 0;
} else if (argc >= 3 && strcmp(argv[1], "trace") == 0) { } else if (argc >= 3 && strcmp(argv[1], "trace") == 0) {
if (argc >= 4 && strcmp(argv[3], "--restart") == 0) zygiskd::ZygoteRestart(); if (argc >= 4 && strcmp(argv[3], "--restart") == 0) rezygiskd_zygote_restart();
long pid = strtol(argv[2], 0, 0); long pid = strtol(argv[2], 0, 0);
if (!trace_zygote(pid)) { if (!trace_zygote(pid)) {
@@ -54,28 +54,28 @@ int main(int argc, char **argv) {
return 0; return 0;
} else if (argc >= 2 && strcmp(argv[1], "info") == 0) { } else if (argc >= 2 && strcmp(argv[1], "info") == 0) {
struct zygote_info info; struct rezygisk_info info;
zygiskd::GetInfo(&info); rezygiskd_get_info(&info);
printf("Daemon process PID: %d\n", info.pid); printf("Daemon process PID: %d\n", info.pid);
switch (info.root_impl) { switch (info.root_impl) {
case ZYGOTE_ROOT_IMPL_NONE: { case ROOT_IMPL_NONE: {
printf("Root implementation: none\n"); printf("Root implementation: none\n");
break; break;
} }
case ZYGOTE_ROOT_IMPL_APATCH: { case ROOT_IMPL_APATCH: {
printf("Root implementation: APatch\n"); printf("Root implementation: APatch\n");
break; break;
} }
case ZYGOTE_ROOT_IMPL_KERNELSU: { case ROOT_IMPL_KERNELSU: {
printf("Root implementation: KernelSU\n"); printf("Root implementation: KernelSU\n");
break; break;
} }
case ZYGOTE_ROOT_IMPL_MAGISK: { case ROOT_IMPL_MAGISK: {
printf("Root implementation: Magisk\n"); printf("Root implementation: Magisk\n");
break; break;

View File

@@ -14,8 +14,7 @@
#include "monitor.h" #include "monitor.h"
#include "utils.hpp" #include "utils.hpp"
#include "files.hpp" #include "misc.h"
#include "misc.hpp"
#define STOPPED_WITH(sig, event) WIFSTOPPED(status) && (status >> 8 == ((sig) | (event << 8))) #define STOPPED_WITH(sig, event) WIFSTOPPED(status) && (status >> 8 == ((sig) | (event << 8)))
@@ -140,7 +139,10 @@ struct SocketHandler : public EventHandler {
.sun_path = { 0 } .sun_path = { 0 }
}; };
size_t sun_path_len = sprintf(addr.sun_path, "%s/%s", zygiskd::GetTmpPath().c_str(), SOCKET_NAME); char tmp_path[PATH_MAX];
rezygiskd_get_path(tmp_path, sizeof(tmp_path));
size_t sun_path_len = sprintf(addr.sun_path, "%s/%s", tmp_path, SOCKET_NAME);
socklen_t socklen = sizeof(sa_family_t) + sun_path_len; socklen_t socklen = sizeof(sa_family_t) + sun_path_len;
if (bind(sock_fd_, (struct sockaddr *)&addr, socklen) == -1) { if (bind(sock_fd_, (struct sockaddr *)&addr, socklen) == -1) {
@@ -747,7 +749,10 @@ static void updateStatus() {
} }
static bool prepare_environment() { static bool prepare_environment() {
strcat(prop_path, zygiskd::GetTmpPath().c_str()); char tmp_path[PATH_MAX];
rezygiskd_get_path(tmp_path, sizeof(tmp_path));
strcat(prop_path, tmp_path);
strcat(prop_path, "/module.prop"); strcat(prop_path, "/module.prop");
close(open(prop_path, O_WRONLY | O_CREAT | O_TRUNC, 0644)); close(open(prop_path, O_WRONLY | O_CREAT | O_TRUNC, 0644));
@@ -817,7 +822,11 @@ int send_control_command(enum Command cmd) {
.sun_path = { 0 } .sun_path = { 0 }
}; };
size_t sun_path_len = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", zygiskd::GetTmpPath().c_str(), SOCKET_NAME); char tmp_path[PATH_MAX];
rezygiskd_get_path(tmp_path, sizeof(tmp_path));
size_t sun_path_len = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", tmp_path, SOCKET_NAME);
socklen_t socklen = sizeof(sa_family_t) + sun_path_len; socklen_t socklen = sizeof(sa_family_t) + sun_path_len;
ssize_t nsend = sendto(sockfd, (void *)&cmd, sizeof(cmd), 0, (sockaddr *)&addr, socklen); ssize_t nsend = sendto(sockfd, (void *)&cmd, sizeof(cmd), 0, (sockaddr *)&addr, socklen);

View File

@@ -240,7 +240,11 @@ bool inject_on_main(int pid, const char *lib_path) {
args.clear(); args.clear();
args.push_back((uintptr_t) start_addr); args.push_back((uintptr_t) start_addr);
args.push_back(block_size); args.push_back(block_size);
str = push_string(pid, regs, zygiskd::GetTmpPath().c_str());
char tmp_path[PATH_MAX];
rezygiskd_get_path(tmp_path, sizeof(tmp_path));
str = push_string(pid, regs, tmp_path);
args.push_back((long) str); args.push_back((long) str);
remote_call(pid, regs, injector_entry, (uintptr_t)libc_return_addr, args); remote_call(pid, regs, injector_entry, (uintptr_t)libc_return_addr, args);
@@ -287,10 +291,12 @@ bool trace_zygote(int pid) {
if (STOPPED_WITH(SIGSTOP, PTRACE_EVENT_STOP)) { if (STOPPED_WITH(SIGSTOP, PTRACE_EVENT_STOP)) {
/* WARNING: C++ keyword */ /* WARNING: C++ keyword */
std::string lib_path = zygiskd::GetTmpPath(); char lib_path[PATH_MAX];
lib_path += "/lib" LP_SELECT("", "64") "/libzygisk.so"; rezygiskd_get_path(lib_path, sizeof(lib_path));
if (!inject_on_main(pid, lib_path.c_str())) { strcat(lib_path,"/lib" LP_SELECT("", "64") "/libzygisk.so");
if (!inject_on_main(pid, lib_path)) {
LOGE("failed to inject"); LOGE("failed to inject");
return false; return false;