You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
Compare commits
5 Commits
7e823319b7
...
3688df6450
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3688df6450 | ||
|
|
0c7a756030 | ||
|
|
70805bb390 | ||
|
|
e6344d2e12 | ||
|
|
d2ebb2bfed |
@@ -57,7 +57,6 @@ android {
|
||||
defaultConfig {
|
||||
externalNativeBuild.cmake {
|
||||
arguments += "-DANDROID_STL=none"
|
||||
arguments += "-DLSPLT_STANDALONE=ON"
|
||||
arguments += "-DCMAKE_BUILD_PARALLEL_LEVEL=${Runtime.getRuntime().availableProcessors()}"
|
||||
cFlags("-std=c18", *defaultCFlags)
|
||||
cppFlags("-std=c++20", *defaultCFlags)
|
||||
|
||||
@@ -15,7 +15,7 @@ target_link_libraries(common log)
|
||||
aux_source_directory(injector INJECTOR_SRC_LIST)
|
||||
add_library(zygisk SHARED ${INJECTOR_SRC_LIST})
|
||||
target_include_directories(zygisk PRIVATE include)
|
||||
target_link_libraries(zygisk cxx::cxx log common lsplt_static phmap)
|
||||
target_link_libraries(zygisk cxx::cxx log common lsplt_static)
|
||||
|
||||
aux_source_directory(ptracer PTRACER_SRC_LIST)
|
||||
add_executable(libzygisk_ptrace.so ${PTRACER_SRC_LIST})
|
||||
|
||||
@@ -8,6 +8,50 @@
|
||||
|
||||
#include "socket_utils.h"
|
||||
|
||||
ssize_t write_loop(int fd, const void *buf, size_t count) {
|
||||
ssize_t written = 0;
|
||||
while (written < (ssize_t)count) {
|
||||
ssize_t ret = write(fd, (const char *)buf + written, count - written);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) continue;
|
||||
|
||||
PLOGE("write");
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
LOGE("write: 0 bytes written");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
written += ret;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
ssize_t read_loop(int fd, void *buf, size_t count) {
|
||||
ssize_t read_bytes = 0;
|
||||
while (read_bytes < (ssize_t)count) {
|
||||
ssize_t ret = read(fd, (char *)buf + read_bytes, count - read_bytes);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) continue;
|
||||
|
||||
PLOGE("read");
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
LOGE("read: 0 bytes read");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_bytes += ret;
|
||||
}
|
||||
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
/* TODO: Standardize how to log errors */
|
||||
int read_fd(int fd) {
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
@@ -47,14 +91,14 @@ int read_fd(int fd) {
|
||||
|
||||
ssize_t write_string(int fd, const char *str) {
|
||||
size_t str_len = strlen(str);
|
||||
ssize_t write_bytes = TEMP_FAILURE_RETRY(write(fd, &str_len, sizeof(size_t)));
|
||||
ssize_t write_bytes = write_loop(fd, &str_len, sizeof(size_t));
|
||||
if (write_bytes != (ssize_t)sizeof(size_t)) {
|
||||
LOGE("Failed to write string length: Not all bytes were written (%zd != %zu).\n", write_bytes, sizeof(size_t));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_bytes = TEMP_FAILURE_RETRY(write(fd, str, str_len));
|
||||
write_bytes = write_loop(fd, str, str_len);
|
||||
if (write_bytes != (ssize_t)str_len) {
|
||||
LOGE("Failed to write string: Promised bytes doesn't exist (%zd != %zu).\n", write_bytes, str_len);
|
||||
|
||||
@@ -66,7 +110,7 @@ ssize_t write_string(int fd, const char *str) {
|
||||
|
||||
char *read_string(int fd) {
|
||||
size_t str_len = 0;
|
||||
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, &str_len, sizeof(size_t)));
|
||||
ssize_t read_bytes = read_loop(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));
|
||||
|
||||
@@ -80,7 +124,7 @@ char *read_string(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read_bytes = TEMP_FAILURE_RETRY(read(fd, buf, str_len));
|
||||
read_bytes = read_loop(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);
|
||||
|
||||
@@ -94,14 +138,14 @@ char *read_string(int fd) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define write_func(type) \
|
||||
ssize_t write_## type(int fd, type val) { \
|
||||
return TEMP_FAILURE_RETRY(write(fd, &val, sizeof(type))); \
|
||||
#define write_func(type) \
|
||||
ssize_t write_## type(int fd, type val) { \
|
||||
return write_loop(fd, &val, sizeof(type)); \
|
||||
}
|
||||
|
||||
#define read_func(type) \
|
||||
ssize_t read_## type(int fd, type *val) { \
|
||||
return TEMP_FAILURE_RETRY(read(fd, val, sizeof(type))); \
|
||||
#define read_func(type) \
|
||||
ssize_t read_## type(int fd, type *val) { \
|
||||
return read_loop(fd, val, sizeof(type)); \
|
||||
}
|
||||
|
||||
write_func(uint8_t)
|
||||
|
||||
4
loader/src/external/CMakeLists.txt
vendored
4
loader/src/external/CMakeLists.txt
vendored
@@ -2,7 +2,3 @@ project(external)
|
||||
|
||||
OPTION(LSPLT_BUILD_SHARED OFF)
|
||||
add_subdirectory(lsplt/lsplt/src/main/jni)
|
||||
|
||||
add_library(phmap INTERFACE)
|
||||
target_include_directories(phmap INTERFACE parallel-hashmap)
|
||||
target_compile_options(phmap INTERFACE -Wno-unused-value)
|
||||
|
||||
2
loader/src/external/lsplt
vendored
2
loader/src/external/lsplt
vendored
Submodule loader/src/external/lsplt updated: 4a1622f072...5092fb399f
@@ -3,6 +3,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
ssize_t write_loop(int fd, const void *buf, size_t count);
|
||||
|
||||
ssize_t read_loop(int fd, void *buf, size_t count);
|
||||
|
||||
int read_fd(int fd);
|
||||
|
||||
ssize_t write_string(int fd, const char *str);
|
||||
|
||||
@@ -822,52 +822,52 @@ void ZygiskContext::app_specialize_pre() {
|
||||
if Zygisk is enabled.
|
||||
*/
|
||||
setenv("ZYGISK_ENABLED", "1", 1);
|
||||
} else {
|
||||
/* INFO: Because we load directly from the file, we need to do it before we umount
|
||||
the mounts, or else it won't have access to /data/adb anymore.
|
||||
*/
|
||||
if (!load_modules_only()) {
|
||||
LOGE("Failed to load modules");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* INFO: Modules only have two "start off" points from Zygisk, preSpecialize and
|
||||
postSpecialize. In preSpecialize, the process still has privileged
|
||||
permissions, and therefore can execute mount/umount/setns functions.
|
||||
If we update the mount namespace AFTER executing them, any mounts made
|
||||
will be lost, and the process will not have access to them anymore.
|
||||
|
||||
In postSpecialize, while still could have its mounts modified with the
|
||||
assistance of a Zygisk companion, it will already have the mount
|
||||
namespace switched by then, so there won't be issues.
|
||||
|
||||
Knowing this, we update the mns before execution, so that they can still
|
||||
make changes to mounts in DenyListed processes without being reverted.
|
||||
*/
|
||||
bool in_denylist = (info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST;
|
||||
if (in_denylist) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
|
||||
/* INFO: Executed after setns to ensure a module can update the mounts of an
|
||||
application without worrying about it being overwritten by setns.
|
||||
*/
|
||||
run_modules_pre();
|
||||
|
||||
/* INFO: The modules may request that although the process is NOT in
|
||||
the DenyList, it has its mount namespace switched to the clean
|
||||
one.
|
||||
|
||||
So to ensure this behavior happens, we must also check after the
|
||||
modules are loaded and executed, so that the modules can have
|
||||
the chance to request it.
|
||||
*/
|
||||
if (!in_denylist && flags[DO_REVERT_UNMOUNT])
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
|
||||
/* INFO: Because we load directly from the file, we need to do it before we umount
|
||||
the mounts, or else it won't have access to /data/adb anymore.
|
||||
*/
|
||||
if (!load_modules_only()) {
|
||||
LOGE("Failed to load modules");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* INFO: Modules only have two "start off" points from Zygisk, preSpecialize and
|
||||
postSpecialize. In preSpecialize, the process still has privileged
|
||||
permissions, and therefore can execute mount/umount/setns functions.
|
||||
If we update the mount namespace AFTER executing them, any mounts made
|
||||
will be lost, and the process will not have access to them anymore.
|
||||
|
||||
In postSpecialize, while still could have its mounts modified with the
|
||||
assistance of a Zygisk companion, it will already have the mount
|
||||
namespace switched by then, so there won't be issues.
|
||||
|
||||
Knowing this, we update the mns before execution, so that they can still
|
||||
make changes to mounts in DenyListed processes without being reverted.
|
||||
*/
|
||||
bool in_denylist = (info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST;
|
||||
if (in_denylist) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
|
||||
/* INFO: Executed after setns to ensure a module can update the mounts of an
|
||||
application without worrying about it being overwritten by setns.
|
||||
*/
|
||||
run_modules_pre();
|
||||
|
||||
/* INFO: The modules may request that although the process is NOT in
|
||||
the DenyList, it has its mount namespace switched to the clean
|
||||
one.
|
||||
|
||||
So to ensure this behavior happens, we must also check after the
|
||||
modules are loaded and executed, so that the modules can have
|
||||
the chance to request it.
|
||||
*/
|
||||
if (!in_denylist && flags[DO_REVERT_UNMOUNT])
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
||||
static void (*soinfo_free)(SoInfo *) = NULL;
|
||||
static SoInfo *(*find_containing_library)(const void *p) = NULL;
|
||||
static void (*purge_unused_memory)(void) = NULL;
|
||||
struct link_map *r_debug_tail = NULL;
|
||||
|
||||
static inline const char *get_path(SoInfo *self) {
|
||||
if (get_realpath_sym)
|
||||
@@ -150,6 +151,17 @@ static bool solist_init() {
|
||||
|
||||
LOGD("%p is purge_unused_memory", (void *)purge_unused_memory);
|
||||
|
||||
r_debug_tail = (struct link_map *)getSymbValueByPrefix(linker, "__dl__ZL12r_debug_tail");
|
||||
if (r_debug_tail == NULL) {
|
||||
LOGE("Failed to find r_debug_tail __dl__ZL10r_debug_tail");
|
||||
|
||||
ElfImg_destroy(linker);
|
||||
|
||||
somain = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
g_module_load_counter = (size_t *)getSymbAddress(linker, "__dl__ZL21g_module_load_counter");
|
||||
if (g_module_load_counter != NULL) LOGD("found symbol g_module_load_counter");
|
||||
|
||||
@@ -173,6 +185,58 @@ static bool solist_init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* INFO: This is an AOSP function to remove a link map from
|
||||
the link map list.
|
||||
|
||||
SOURCES:
|
||||
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker_gdb_support.cpp#63
|
||||
*/
|
||||
static void remove_link_map_from_debug_map(struct link_map *map) {
|
||||
if (r_debug_tail == map) {
|
||||
r_debug_tail = map->l_prev;
|
||||
}
|
||||
|
||||
if (map->l_prev) {
|
||||
map->l_prev->l_next = map->l_next;
|
||||
}
|
||||
|
||||
if (map->l_next) {
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
}
|
||||
}
|
||||
|
||||
static struct link_map *find_link_map(SoInfo *si) {
|
||||
const char *path = get_path(si);
|
||||
if (path == NULL) {
|
||||
LOGE("Failed to get path for SoInfo %p", (void *)si);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOGD("Searching for link_map for %s", path);
|
||||
|
||||
struct link_map *map = r_debug_tail;
|
||||
while (map) {
|
||||
/* INFO: l_name uses the same pointer as realpath function of SoInfo, allowing us
|
||||
to directly compare the pointers instead of the strings.
|
||||
|
||||
SOURCES:
|
||||
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#283
|
||||
*/
|
||||
if (map->l_name && (uintptr_t)map->l_name == (uintptr_t)path) {
|
||||
LOGD("Found link_map for %s: %p", path, (void *)map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
map = map->l_next;
|
||||
}
|
||||
|
||||
LOGE("Failed to find link_map for %s", path);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* INFO: find_containing_library returns the SoInfo for the library that contains
|
||||
that memory inside its limits, hence why named "lib_memory" in ReZygisk. */
|
||||
bool solist_drop_so_path(void *lib_memory, bool unload) {
|
||||
@@ -219,11 +283,24 @@ bool solist_drop_so_path(void *lib_memory, bool unload) {
|
||||
} else if (!unload) {
|
||||
LOGD("Not unloading so path for %s, only dropping it", path);
|
||||
|
||||
/* TODO: call notify_gdb_of_unload(found); (it is static) to avoid leaving traces in
|
||||
r_debug_tail.
|
||||
SOURCES:
|
||||
- https://android.googlesource.com/platform/bionic/+/refs/heads/main/linker/linker_gdb_support.cpp#94
|
||||
/*
|
||||
INFO: If the link map is not removed from the list, it gets inconsistent, resulting
|
||||
in a loop when listing through it, which can be detected. To fix that, we
|
||||
can remove the map, like expected.
|
||||
|
||||
We cannot use the notify_gdb_of_unload function as it is static, and not available
|
||||
in all linker binaries.
|
||||
*/
|
||||
struct link_map *map = find_link_map(found);
|
||||
if (!map) {
|
||||
LOGE("Failed to find link map for %s", path);
|
||||
|
||||
pdg_protect();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
remove_link_map_from_debug_map(map);
|
||||
/* INFO: unregister_soinfo_tls cannot be used since module might use JNI which may
|
||||
require TLS, so we cannot remove it. */
|
||||
soinfo_free(found);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "utils.h"
|
||||
#include "daemon.h"
|
||||
#include "misc.h"
|
||||
#include "socket_utils.h"
|
||||
|
||||
#include "monitor.h"
|
||||
|
||||
@@ -29,6 +30,15 @@ static bool update_status(const char *message);
|
||||
|
||||
char monitor_stop_reason[32];
|
||||
|
||||
struct environment_information {
|
||||
char *root_impl;
|
||||
char **modules;
|
||||
uint32_t modules_len;
|
||||
};
|
||||
|
||||
static struct environment_information environment_information64;
|
||||
static struct environment_information environment_information32;
|
||||
|
||||
enum ptracer_tracing_state {
|
||||
TRACING,
|
||||
STOPPING,
|
||||
@@ -158,57 +168,26 @@ bool rezygiskd_listener_init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct __attribute__((__packed__)) MsgHead {
|
||||
unsigned int cmd;
|
||||
int length;
|
||||
};
|
||||
|
||||
void rezygiskd_listener_callback() {
|
||||
while (1) {
|
||||
struct MsgHead msg = { 0 };
|
||||
uint8_t cmd;
|
||||
ssize_t nread = TEMP_FAILURE_RETRY(read(monitor_sock_fd, &cmd, sizeof(cmd)));
|
||||
if (nread == -1) {
|
||||
PLOGE("read socket");
|
||||
|
||||
size_t nread;
|
||||
|
||||
again:
|
||||
nread = read(monitor_sock_fd, &msg, sizeof(msg));
|
||||
if ((int)nread == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) goto again;
|
||||
|
||||
PLOGE("read socket");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char *msg_data = NULL;
|
||||
|
||||
if (msg.length != 0) {
|
||||
msg_data = malloc(msg.length);
|
||||
if (!msg_data) {
|
||||
LOGE("malloc msg data failed");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
again_msg_data:
|
||||
nread = read(monitor_sock_fd, msg_data, msg.length);
|
||||
if ((int)nread == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) goto again_msg_data;
|
||||
|
||||
PLOGE("read socket");
|
||||
|
||||
free(msg_data);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (msg.cmd) {
|
||||
switch (cmd) {
|
||||
case START: {
|
||||
if (tracing_state == STOPPING) tracing_state = TRACING;
|
||||
else if (tracing_state == STOPPED) {
|
||||
ptrace(PTRACE_SEIZE, 1, 0, PTRACE_O_TRACEFORK);
|
||||
if (tracing_state == STOPPING) {
|
||||
LOGI("Continue tracing init");
|
||||
|
||||
LOGI("start tracing init");
|
||||
tracing_state = TRACING;
|
||||
} else if (tracing_state == STOPPED) {
|
||||
LOGI("Start tracing init");
|
||||
|
||||
ptrace(PTRACE_SEIZE, 1, 0, PTRACE_O_TRACEFORK);
|
||||
|
||||
tracing_state = TRACING;
|
||||
}
|
||||
@@ -219,7 +198,7 @@ void rezygiskd_listener_callback() {
|
||||
}
|
||||
case STOP: {
|
||||
if (tracing_state == TRACING) {
|
||||
LOGI("stop tracing requested");
|
||||
LOGI("Stop tracing requested");
|
||||
|
||||
tracing_state = STOPPING;
|
||||
strcpy(monitor_stop_reason, "user requested");
|
||||
@@ -231,7 +210,7 @@ void rezygiskd_listener_callback() {
|
||||
break;
|
||||
}
|
||||
case EXIT: {
|
||||
LOGI("prepare for exit ...");
|
||||
LOGI("Prepare for exit ...");
|
||||
|
||||
tracing_state = EXITING;
|
||||
strcpy(monitor_stop_reason, "user requested");
|
||||
@@ -241,97 +220,167 @@ void rezygiskd_listener_callback() {
|
||||
|
||||
break;
|
||||
}
|
||||
case ZYGOTE64_INJECTED: {
|
||||
status64.zygote_injected = true;
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
case ZYGOTE64_INJECTED:
|
||||
case ZYGOTE32_INJECTED: {
|
||||
status32.zygote_injected = true;
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
case DAEMON64_SET_INFO: {
|
||||
LOGD("received daemon64 info %s", msg_data);
|
||||
|
||||
/* Will only happen if somehow the daemon restarts */
|
||||
if (status64.daemon_info) {
|
||||
free(status64.daemon_info);
|
||||
status64.daemon_info = NULL;
|
||||
}
|
||||
|
||||
status64.daemon_info = strdup(msg_data);
|
||||
if (!status64.daemon_info) {
|
||||
PLOGE("malloc daemon64 info");
|
||||
|
||||
break;
|
||||
}
|
||||
LOGI("Received Zygote%s injected command", cmd == ZYGOTE64_INJECTED ? "64" : "32");
|
||||
|
||||
struct rezygiskd_status *status = cmd == ZYGOTE64_INJECTED ? &status64 : &status32;
|
||||
status->zygote_injected = true;
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
case DAEMON64_SET_INFO:
|
||||
case DAEMON32_SET_INFO: {
|
||||
LOGD("received daemon32 info %s", msg_data);
|
||||
LOGD("Received ReZygiskd%s info", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
if (status32.daemon_info) {
|
||||
free(status32.daemon_info);
|
||||
status32.daemon_info = NULL;
|
||||
}
|
||||
|
||||
status32.daemon_info = strdup(msg_data);
|
||||
if (!status32.daemon_info) {
|
||||
PLOGE("malloc daemon32 info");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
case DAEMON64_SET_ERROR_INFO: {
|
||||
LOGD("received daemon64 error info %s", msg_data);
|
||||
|
||||
status64.daemon_running = false;
|
||||
|
||||
if (status64.daemon_error_info) {
|
||||
free(status64.daemon_error_info);
|
||||
status64.daemon_error_info = NULL;
|
||||
}
|
||||
|
||||
status64.daemon_error_info = strdup(msg_data);
|
||||
if (!status64.daemon_error_info) {
|
||||
PLOGE("malloc daemon64 error info");
|
||||
uint32_t root_impl_len;
|
||||
if (read_uint32_t(monitor_sock_fd, &root_impl_len) != sizeof(root_impl_len)) {
|
||||
LOGE("read ReZygiskd%s root impl len", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
struct environment_information *environment_information = cmd == DAEMON64_SET_INFO ? &environment_information64 : &environment_information32;
|
||||
if (environment_information->root_impl) {
|
||||
LOGD("freeing old ReZygiskd%s root impl", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
free((void *)environment_information->root_impl);
|
||||
environment_information->root_impl = NULL;
|
||||
}
|
||||
|
||||
environment_information->root_impl = malloc(root_impl_len + 1);
|
||||
if (environment_information->root_impl == NULL) {
|
||||
PLOGE("malloc ReZygiskd%s root impl", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (read_loop(monitor_sock_fd, (void *)environment_information->root_impl, root_impl_len) != (ssize_t)root_impl_len) {
|
||||
LOGE("read ReZygiskd%s root impl", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
free((void *)environment_information->root_impl);
|
||||
environment_information->root_impl = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
environment_information->root_impl[root_impl_len] = '\0';
|
||||
LOGD("ReZygiskd%s root impl: %s", cmd == DAEMON64_SET_INFO ? "64" : "32", environment_information->root_impl);
|
||||
|
||||
if (read_uint32_t(monitor_sock_fd, &environment_information->modules_len) != sizeof(environment_information->modules_len)) {
|
||||
LOGE("read ReZygiskd%s modules len", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
free((void *)environment_information->root_impl);
|
||||
environment_information->root_impl = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (environment_information->modules) {
|
||||
LOGD("freeing old ReZygiskd%s modules", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
for (size_t i = 0; i < environment_information->modules_len; i++) {
|
||||
free((void *)environment_information->modules[i]);
|
||||
}
|
||||
|
||||
free((void *)environment_information->modules);
|
||||
environment_information->modules = NULL;
|
||||
}
|
||||
|
||||
environment_information->modules = malloc(environment_information->modules_len * sizeof(char *));
|
||||
if (environment_information->modules == NULL) {
|
||||
PLOGE("malloc ReZygiskd%s modules", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
free((void *)environment_information->root_impl);
|
||||
environment_information->root_impl = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < environment_information->modules_len; i++) {
|
||||
uint32_t module_name_len;
|
||||
if (read_uint32_t(monitor_sock_fd, &module_name_len) != sizeof(module_name_len)) {
|
||||
LOGE("read ReZygiskd%s module name len", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
goto rezygiskd64_set_info_modules_cleanup;
|
||||
}
|
||||
|
||||
environment_information->modules[i] = malloc(module_name_len + 1);
|
||||
if (environment_information->modules[i] == NULL) {
|
||||
PLOGE("malloc ReZygiskd%s module name", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
goto rezygiskd64_set_info_modules_cleanup;
|
||||
}
|
||||
|
||||
if (read_loop(monitor_sock_fd, (void *)environment_information->modules[i], module_name_len) != (ssize_t)module_name_len) {
|
||||
LOGE("read ReZygiskd%s module name", cmd == DAEMON64_SET_INFO ? "64" : "32");
|
||||
|
||||
goto rezygiskd64_set_info_modules_cleanup;
|
||||
}
|
||||
|
||||
environment_information->modules[i][module_name_len] = '\0';
|
||||
LOGD("ReZygiskd%s module %zu: %s", cmd == DAEMON64_SET_INFO ? "64" : "32", i, environment_information->modules[i]);
|
||||
|
||||
continue;
|
||||
|
||||
rezygiskd64_set_info_modules_cleanup:
|
||||
free((void *)environment_information->root_impl);
|
||||
environment_information->root_impl = NULL;
|
||||
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
free((void *)environment_information->modules[j]);
|
||||
}
|
||||
|
||||
free((void *)environment_information->modules);
|
||||
environment_information->modules = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
case DAEMON64_SET_ERROR_INFO:
|
||||
case DAEMON32_SET_ERROR_INFO: {
|
||||
LOGD("received daemon32 error info %s", msg_data);
|
||||
LOGD("Received ReZygiskd%s error info", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32");
|
||||
|
||||
status32.daemon_running = false;
|
||||
|
||||
if (status32.daemon_error_info) {
|
||||
free(status32.daemon_error_info);
|
||||
status32.daemon_error_info = NULL;
|
||||
}
|
||||
|
||||
status32.daemon_error_info = strdup(msg_data);
|
||||
if (!status32.daemon_error_info) {
|
||||
PLOGE("malloc daemon32 error info");
|
||||
uint32_t error_info_len;
|
||||
if (read_uint32_t(monitor_sock_fd, &error_info_len) != sizeof(error_info_len)) {
|
||||
LOGE("read ReZygiskd%s error info len", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
struct rezygiskd_status *status = cmd == DAEMON64_SET_ERROR_INFO ? &status64 : &status32;
|
||||
if (status->daemon_error_info) {
|
||||
LOGD("freeing old ReZygiskd%s error info", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32");
|
||||
|
||||
free(status->daemon_error_info);
|
||||
status->daemon_error_info = NULL;
|
||||
}
|
||||
|
||||
status->daemon_error_info = malloc(error_info_len + 1);
|
||||
if (status->daemon_error_info == NULL) {
|
||||
PLOGE("malloc ReZygiskd%s error info", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (read_loop(monitor_sock_fd, status->daemon_error_info, error_info_len) != (ssize_t)error_info_len) {
|
||||
LOGE("read ReZygiskd%s error info", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32");
|
||||
|
||||
free(status->daemon_error_info);
|
||||
status->daemon_error_info = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
status->daemon_error_info[error_info_len] = '\0';
|
||||
LOGD("ReZygiskd%s error info: %s", cmd == DAEMON64_SET_ERROR_INFO ? "64" : "32", status->daemon_error_info);
|
||||
|
||||
update_status(NULL);
|
||||
|
||||
break;
|
||||
@@ -347,8 +396,6 @@ void rezygiskd_listener_callback() {
|
||||
}
|
||||
}
|
||||
|
||||
if (msg_data) free(msg_data);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -423,51 +470,49 @@ static bool ensure_daemon_created(bool is_64bit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CHECK_DAEMON_EXIT(abi) \
|
||||
if (status##abi.supported && pid == status##abi.daemon_pid) { \
|
||||
char status_str[64]; \
|
||||
parse_status(sigchld_status, status_str, sizeof(status_str)); \
|
||||
\
|
||||
LOGW("daemon" #abi " pid %d exited: %s", pid, status_str); \
|
||||
status##abi.daemon_running = false; \
|
||||
\
|
||||
if (!status##abi.daemon_error_info) { \
|
||||
status##abi.daemon_error_info = (char *)malloc(strlen(status_str) + 1); \
|
||||
if (!status##abi.daemon_error_info) { \
|
||||
LOGE("malloc daemon" #abi " error info failed"); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
memcpy(status##abi.daemon_error_info, status_str, strlen(status_str) + 1); \
|
||||
} \
|
||||
\
|
||||
update_status(NULL); \
|
||||
continue; \
|
||||
#define CHECK_DAEMON_EXIT(abi) \
|
||||
if (status##abi.supported && pid == status##abi.daemon_pid) { \
|
||||
char status_str[64]; \
|
||||
parse_status(sigchld_status, status_str, sizeof(status_str)); \
|
||||
\
|
||||
LOGW("daemon" #abi " pid %d exited: %s", pid, status_str); \
|
||||
status##abi.daemon_running = false; \
|
||||
\
|
||||
if (!status##abi.daemon_error_info) { \
|
||||
status##abi.daemon_error_info = strdup(status_str); \
|
||||
if (!status##abi.daemon_error_info) { \
|
||||
LOGE("malloc daemon" #abi " error info failed"); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define PRE_INJECT(abi, is_64) \
|
||||
if (strcmp(program, "/system/bin/app_process" # abi) == 0) { \
|
||||
tracer = "./bin/zygisk-ptrace" # abi; \
|
||||
\
|
||||
if (should_stop_inject ## abi()) { \
|
||||
LOGW("zygote" # abi " restart too much times, stop injecting"); \
|
||||
\
|
||||
tracing_state = STOPPING; \
|
||||
memcpy(monitor_stop_reason, "zygote crashed", sizeof("zygote crashed")); \
|
||||
ptrace(PTRACE_INTERRUPT, 1, 0, 0); \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
if (!ensure_daemon_created(is_64)) { \
|
||||
LOGW("daemon" #abi " not running, stop injecting"); \
|
||||
\
|
||||
tracing_state = STOPPING; \
|
||||
memcpy(monitor_stop_reason, "daemon not running", sizeof("daemon not running")); \
|
||||
ptrace(PTRACE_INTERRUPT, 1, 0, 0); \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
#define PRE_INJECT(abi, is_64) \
|
||||
if (strcmp(program, "/system/bin/app_process" # abi) == 0) { \
|
||||
tracer = "./bin/zygisk-ptrace" # abi; \
|
||||
\
|
||||
if (should_stop_inject ## abi()) { \
|
||||
LOGW("Zygote" # abi " restart too much times, stop injecting"); \
|
||||
\
|
||||
tracing_state = STOPPING; \
|
||||
strcpy(monitor_stop_reason, "Zygote crashed"); \
|
||||
ptrace(PTRACE_INTERRUPT, 1, 0, 0); \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (!ensure_daemon_created(is_64)) { \
|
||||
LOGW("ReZygiskd " #abi "-bit not running, stop injecting"); \
|
||||
\
|
||||
tracing_state = STOPPING; \
|
||||
strcpy(monitor_stop_reason, "ReZygiskd not running"); \
|
||||
ptrace(PTRACE_INTERRUPT, 1, 0, 0); \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
int sigchld_signal_fd;
|
||||
@@ -661,8 +706,6 @@ void sigchld_listener_callback() {
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
||||
update_status(NULL);
|
||||
} else {
|
||||
char status_str[64];
|
||||
parse_status(sigchld_status, status_str, sizeof(status_str));
|
||||
@@ -702,27 +745,20 @@ static char post_section[1024];
|
||||
|
||||
#define WRITE_STATUS_ABI(suffix) \
|
||||
if (status ## suffix.supported) { \
|
||||
strcat(status_text, " zygote" # suffix ": "); \
|
||||
if (tracing_state != TRACING) strcat(status_text, "❓ unknown, "); \
|
||||
else if (status ## suffix.zygote_injected) strcat(status_text, "😋 injected, "); \
|
||||
else strcat(status_text, "❌ not injected, "); \
|
||||
strcat(status_text, ", ReZygisk " # suffix "-bit: "); \
|
||||
\
|
||||
strcat(status_text, "daemon" # suffix ": "); \
|
||||
if (status ## suffix.daemon_running) { \
|
||||
strcat(status_text, "😋 running "); \
|
||||
if (tracing_state != TRACING) strcat(status_text, "❌"); \
|
||||
else if (status ## suffix.zygote_injected && status ## suffix.daemon_running) \
|
||||
strcat(status_text, "✅"); \
|
||||
else strcat(status_text, "⚠️"); \
|
||||
\
|
||||
if (status ## suffix.daemon_info != NULL) { \
|
||||
strcat(status_text, "("); \
|
||||
strcat(status_text, status ## suffix.daemon_info); \
|
||||
strcat(status_text, ")"); \
|
||||
} \
|
||||
} else { \
|
||||
strcat(status_text, "❌ crashed "); \
|
||||
\
|
||||
if (status ## suffix.daemon_error_info != NULL) { \
|
||||
strcat(status_text, "("); \
|
||||
if (!status ## suffix.daemon_running) { \
|
||||
if (status ## suffix.daemon_error_info) { \
|
||||
strcat(status_text, "(ReZygiskd: "); \
|
||||
strcat(status_text, status ## suffix.daemon_error_info); \
|
||||
strcat(status_text, ")"); \
|
||||
} else { \
|
||||
strcat(status_text, "(ReZygiskd: not running)"); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
@@ -742,41 +778,106 @@ static bool update_status(const char *message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char status_text[1024] = "monitor: ";
|
||||
|
||||
char status_text[256] = "Monitor: ";
|
||||
switch (tracing_state) {
|
||||
case TRACING: {
|
||||
strcat(status_text, "😋 tracing");
|
||||
strcat(status_text, "✅");
|
||||
|
||||
break;
|
||||
}
|
||||
case STOPPING: [[fallthrough]];
|
||||
case STOPPED: {
|
||||
strcat(status_text, "❌ stopped");
|
||||
strcat(status_text, "⛔");
|
||||
|
||||
break;
|
||||
}
|
||||
case EXITING: {
|
||||
strcat(status_text, "❌ exited");
|
||||
strcat(status_text, "❌");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracing_state != TRACING && monitor_stop_reason[0] != '\0') {
|
||||
strcat(status_text, " (");
|
||||
strcat(status_text, monitor_stop_reason);
|
||||
strcat(status_text, ")");
|
||||
}
|
||||
strcat(status_text, ",");
|
||||
|
||||
WRITE_STATUS_ABI(64)
|
||||
WRITE_STATUS_ABI(32)
|
||||
|
||||
fprintf(prop, "%s[%s] %s", pre_section, status_text, post_section);
|
||||
|
||||
fclose(prop);
|
||||
|
||||
if (environment_information64.root_impl || environment_information32.root_impl) {
|
||||
FILE *json = fopen("/data/adb/rezygisk/state.json", "w");
|
||||
if (json == NULL) {
|
||||
PLOGE("failed to open state.json");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(json, "{\n");
|
||||
fprintf(json, " \"root\": \"%s\",\n", environment_information64.root_impl ? environment_information64.root_impl : environment_information32.root_impl);
|
||||
|
||||
fprintf(json, " \"monitor\": {\n");
|
||||
fprintf(json, " \"state\": \"%d\"", tracing_state);
|
||||
if (monitor_stop_reason[0] != '\0') fprintf(json, ",\n \"reason\": \"%s\",\n", monitor_stop_reason);
|
||||
else fprintf(json, "\n");
|
||||
fprintf(json, " },\n");
|
||||
|
||||
|
||||
fprintf(json, " \"rezygiskd\": {\n");
|
||||
if (status64.supported) {
|
||||
fprintf(json, " \"64\": {\n");
|
||||
fprintf(json, " \"state\": %d,\n", status64.daemon_running);
|
||||
if (status64.daemon_error_info) fprintf(json, " \"reason\": \"%s\",\n", status64.daemon_error_info);
|
||||
fprintf(json, " \"modules\": [");
|
||||
|
||||
if (environment_information64.modules) for (uint32_t i = 0; i < environment_information64.modules_len; i++) {
|
||||
if (i > 0) fprintf(json, ", ");
|
||||
fprintf(json, "\"%s\"", environment_information64.modules[i]);
|
||||
}
|
||||
|
||||
fprintf(json, "]\n");
|
||||
fprintf(json, " }");
|
||||
if (status32.supported) fprintf(json, ",\n");
|
||||
else fprintf(json, "\n");
|
||||
}
|
||||
|
||||
if (status32.supported) {
|
||||
fprintf(json, " \"32\": {\n");
|
||||
fprintf(json, " \"state\": %d,\n", status32.daemon_running);
|
||||
if (status32.daemon_error_info) fprintf(json, " \"reason\": \"%s\",\n", status32.daemon_error_info);
|
||||
fprintf(json, " \"modules\": [");
|
||||
|
||||
if (environment_information32.modules) for (uint32_t i = 0; i < environment_information32.modules_len; i++) {
|
||||
if (i > 0) fprintf(json, ", ");
|
||||
fprintf(json, "\"%s\"", environment_information32.modules[i]);
|
||||
}
|
||||
|
||||
fprintf(json, "]\n");
|
||||
fprintf(json, " }\n");
|
||||
}
|
||||
|
||||
fprintf(json, " },\n");
|
||||
|
||||
fprintf(json, " \"zygote\": {\n");
|
||||
if (status64.supported) {
|
||||
fprintf(json, " \"64\": %d", status64.zygote_injected);
|
||||
if (status32.zygote_injected) fprintf(json, ",\n");
|
||||
else fprintf(json, "\n");
|
||||
}
|
||||
if (status32.zygote_injected) {
|
||||
fprintf(json, " \"32\": %d\n", status32.zygote_injected);
|
||||
}
|
||||
fprintf(json, " }\n");
|
||||
fprintf(json, "}\n");
|
||||
|
||||
fclose(json);
|
||||
} else {
|
||||
if (remove("/data/adb/rezygisk/state.json") == -1) {
|
||||
PLOGE("failed to remove state.json");
|
||||
}
|
||||
}
|
||||
|
||||
LOGI("status updated: %s", status_text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -821,7 +922,7 @@ static bool prepare_environment() {
|
||||
return false;
|
||||
}
|
||||
|
||||
return update_status(NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_monitor() {
|
||||
@@ -864,7 +965,23 @@ void init_monitor() {
|
||||
if (status32.daemon_info) free(status32.daemon_info);
|
||||
if (status32.daemon_error_info) free(status32.daemon_error_info);
|
||||
|
||||
LOGI("exit");
|
||||
if (environment_information64.root_impl) free((void *)environment_information64.root_impl);
|
||||
if (environment_information64.modules) {
|
||||
for (uint32_t i = 0; i < environment_information64.modules_len; i++) {
|
||||
free((void *)environment_information64.modules[i]);
|
||||
}
|
||||
free((void *)environment_information64.modules);
|
||||
}
|
||||
|
||||
if (environment_information32.root_impl) free((void *)environment_information32.root_impl);
|
||||
if (environment_information32.modules) {
|
||||
for (uint32_t i = 0; i < environment_information32.modules_len; i++) {
|
||||
free((void *)environment_information32.modules[i]);
|
||||
}
|
||||
free((void *)environment_information32.modules);
|
||||
}
|
||||
|
||||
LOGI("Terminating ReZygisk monitor");
|
||||
}
|
||||
|
||||
int send_control_command(enum rezygiskd_command cmd) {
|
||||
@@ -880,9 +997,10 @@ int send_control_command(enum rezygiskd_command cmd) {
|
||||
|
||||
socklen_t socklen = sizeof(sa_family_t) + sun_path_len;
|
||||
|
||||
ssize_t nsend = sendto(sockfd, (void *)&cmd, sizeof(cmd), 0, (struct sockaddr *)&addr, socklen);
|
||||
uint8_t cmd_op = cmd;
|
||||
ssize_t nsend = sendto(sockfd, (void *)&cmd_op, sizeof(cmd_op), 0, (struct sockaddr *)&addr, socklen);
|
||||
|
||||
close(sockfd);
|
||||
|
||||
return nsend != sizeof(cmd) ? -1 : 0;
|
||||
return nsend != sizeof(cmd_op) ? -1 : 0;
|
||||
}
|
||||
|
||||
@@ -91,101 +91,106 @@ async function getModuleNames(modules) {
|
||||
const unameCmd = await exec('/system/bin/uname -r')
|
||||
if (unameCmd.errno !== 0) return setError('WebUI', unameCmd.stderr)
|
||||
|
||||
document.getElementById('kernel_version_div').innerHTML = unameCmd.stdout
|
||||
console.log('[rezygisk.js] Kernel version: ', unameCmd.stdout)
|
||||
document.getElementById('kernel_version_div').innerHTML = unameCmd.stdout.trim()
|
||||
console.log('[rezygisk.js] Kernel version: ', unameCmd.stdout.trim())
|
||||
|
||||
const catCmd = await exec('/system/bin/cat /data/adb/rezygisk/module.prop')
|
||||
console.log(`[rezygisk.js] ReZygisk module infomation:\n${catCmd.stdout}`)
|
||||
|
||||
let expectedWorking = 0
|
||||
let actuallyWorking = 0
|
||||
if (catCmd.errno !== 0) {
|
||||
console.error('[rezygisk.js] Failed to retrieve ReZygisk module information:', catCmd.stderr)
|
||||
|
||||
const ReZygiskInfo = {
|
||||
rootImpl: null,
|
||||
monitor: null,
|
||||
zygotes: [],
|
||||
daemons: []
|
||||
}
|
||||
rezygisk_state.innerHTML = translations.page.home.status.notWorking
|
||||
rezygisk_icon_state.innerHTML = '<img class="dimc" src="assets/cross.svg">'
|
||||
|
||||
if (catCmd.errno === 0) {
|
||||
/* INFO: Just ensure that they won't appear unless there's info */
|
||||
rootCss.style.setProperty('--bright', '#766000')
|
||||
|
||||
/* INFO: Hide zygote divs */
|
||||
zygote_divs.forEach((zygote_div) => {
|
||||
zygote_div.style.display = 'none'
|
||||
})
|
||||
|
||||
version.innerHTML = catCmd.stdout.split('\n').find((line) => line.startsWith('version=')).substring('version='.length).trim()
|
||||
loading_screen.style.display = 'none'
|
||||
bottom_nav.style.display = 'flex'
|
||||
|
||||
let moduleInfo = catCmd.stdout.split('\n').find((line) => line.startsWith('description=')).substring('description='.length).split('[')[1].split(']')[0]
|
||||
return;
|
||||
}
|
||||
|
||||
const daemonModules = []
|
||||
moduleInfo.match(/\(([^)]+)\)/g).forEach((area) => {
|
||||
moduleInfo = moduleInfo.replace(area, ',')
|
||||
/* INFO: Just ensure that they won't appear unless there's info */
|
||||
zygote_divs.forEach((zygote_div) => {
|
||||
zygote_div.style.display = 'none'
|
||||
})
|
||||
|
||||
const info = area.substring(1, area.length - 1).split(', ')
|
||||
if (info.length === 1) return; /* INFO: undefined as object */
|
||||
version.innerHTML = catCmd.stdout.split('\n').find((line) => line.startsWith('version=')).substring('version='.length).trim()
|
||||
|
||||
const rootImpl = info[0].substring('Root: '.length)
|
||||
const stateCmd = await exec('/system/bin/cat /data/adb/rezygisk/state.json')
|
||||
if (stateCmd.errno !== 0) {
|
||||
console.error('[rezygisk.js] Failed to retrieve ReZygisk state information:', stateCmd.stderr)
|
||||
|
||||
info[1] = info[1].substring('Modules: '.length)
|
||||
const modules = info.slice(1, info.length)
|
||||
rezygisk_state.innerHTML = translations.page.home.status.notWorking
|
||||
rezygisk_icon_state.innerHTML = '<img class="dimc" src="assets/cross.svg">'
|
||||
|
||||
ReZygiskInfo.rootImpl = rootImpl
|
||||
if (modules[0] !== 'None') daemonModules.push(modules)
|
||||
rootCss.style.setProperty('--bright', '#766000')
|
||||
|
||||
/* INFO: Hide zygote divs */
|
||||
zygote_divs.forEach((zygote_div) => {
|
||||
zygote_div.style.display = 'none'
|
||||
})
|
||||
|
||||
const infoArea = moduleInfo.split(', ')
|
||||
infoArea.forEach((info) => {
|
||||
if (info.startsWith('monitor:')) {
|
||||
ReZygiskInfo.monitor = info.substring('monitor: X '.length).trim()
|
||||
}
|
||||
loading_screen.style.display = 'none'
|
||||
bottom_nav.style.display = 'flex'
|
||||
|
||||
if (info.startsWith('zygote')) {
|
||||
ReZygiskInfo.zygotes.push({
|
||||
bits: info.substring('zygote'.length, 'zygote'.length + 'XX'.length),
|
||||
state: info.substring('zygoteXX: X '.length).trim()
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.startsWith('daemon')) {
|
||||
ReZygiskInfo.daemons.push({
|
||||
bits: info.substring('daemon'.length, 'daemon'.length + 'XX'.length),
|
||||
state: info.substring('daemonXX: X '.length).trim(),
|
||||
modules: daemonModules[ReZygiskInfo.daemons.length] || []
|
||||
})
|
||||
}
|
||||
})
|
||||
const ReZygiskState = JSON.parse(stateCmd.stdout)
|
||||
|
||||
switch (ReZygiskInfo.monitor) {
|
||||
case 'tracing': monitor_status.innerHTML = translations.page.actions.status.tracing; break;
|
||||
case 'stopping': monitor_status.innerHTML = translations.page.actions.status.stopping; break;
|
||||
case 'stopped': monitor_status.innerHTML = translations.page.actions.status.stopped; break;
|
||||
case 'exiting': monitor_status.innerHTML = translations.page.actions.status.exiting; break;
|
||||
default: monitor_status.innerHTML = translations.page.actions.status.unknown;
|
||||
root_impl.innerHTML = ReZygiskState.root
|
||||
|
||||
switch (ReZygiskState.monitor.state) {
|
||||
case 0: monitor_status.innerHTML = translations.page.actions.status.tracing; break;
|
||||
case 1: monitor_status.innerHTML = translations.page.actions.status.stopping; break;
|
||||
case 2: monitor_status.innerHTML = translations.page.actions.status.stopped; break;
|
||||
case 3: monitor_status.innerHTML = translations.page.actions.status.exiting; break;
|
||||
default: monitor_status.innerHTML = translations.page.actions.status.unknown;
|
||||
}
|
||||
|
||||
const expectedWorking = (ReZygiskState.zygote['64'] !== undefined ? 1 : 0) + (ReZygiskState.zygote['32'] !== undefined ? 1 : 0)
|
||||
let actuallyWorking = 0
|
||||
|
||||
if (ReZygiskState.zygote['64'] !== undefined) {
|
||||
const zygote64 = ReZygiskState.zygote['64']
|
||||
|
||||
zygote_divs[0].style.display = 'block'
|
||||
|
||||
switch (zygote64) {
|
||||
case 1: {
|
||||
zygote_status_divs[0].innerHTML = translations.page.home.info.zygote.injected
|
||||
|
||||
actuallyWorking++
|
||||
|
||||
break
|
||||
}
|
||||
case 0: zygote_status_divs[0].innerHTML = translations.page.home.info.zygote.notInjected; break
|
||||
default: zygote_status_divs[0].innerHTML = translations.page.home.info.zygote.unknown
|
||||
}
|
||||
}
|
||||
|
||||
expectedWorking = ReZygiskInfo.zygotes.length
|
||||
if (ReZygiskState.zygote['32'] !== undefined) {
|
||||
const zygote32 = ReZygiskState.zygote['32']
|
||||
|
||||
for (let i = 0; i < ReZygiskInfo.zygotes.length; i++) {
|
||||
const zygote = ReZygiskInfo.zygotes[i]
|
||||
/* INFO: Not used ATM */
|
||||
/* const daemon = ReZygiskInfo.daemons[i] */
|
||||
zygote_divs[1].style.display = 'block'
|
||||
|
||||
const zygoteDiv = zygote_divs[zygote.bits === '64' ? 0 : 1]
|
||||
const zygoteStatusDiv = zygote_status_divs[zygote.bits === '64' ? 0 : 1]
|
||||
switch (zygote32) {
|
||||
case 1: {
|
||||
zygote_status_divs[1].innerHTML = translations.page.home.info.zygote.injected
|
||||
|
||||
zygoteDiv.style.display = 'block'
|
||||
actuallyWorking++
|
||||
|
||||
switch (zygote.state) {
|
||||
case 'injected': {
|
||||
zygoteStatusDiv.innerHTML = translations.page.home.info.zygote.injected;
|
||||
|
||||
actuallyWorking++
|
||||
|
||||
break;
|
||||
}
|
||||
case 'not injected': zygoteStatusDiv.innerHTML = translations.page.home.info.zygote.notInjected; break;
|
||||
default: zygoteStatusDiv.innerHTML = translations.page.home.info.zygote.unknown;
|
||||
break
|
||||
}
|
||||
case 0: zygote_status_divs[1].innerHTML = translations.page.home.info.zygote.notInjected; break
|
||||
default: zygote_status_divs[1].innerHTML = translations.page.home.info.zygote.unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,24 +208,24 @@ async function getModuleNames(modules) {
|
||||
rezygisk_icon_state.innerHTML = '<img class="brightc" src="assets/warn.svg">'
|
||||
}
|
||||
|
||||
if (ReZygiskInfo.rootImpl)
|
||||
root_impl.innerHTML = ReZygiskInfo.rootImpl
|
||||
|
||||
const all_modules = []
|
||||
ReZygiskInfo.daemons.forEach((daemon) => {
|
||||
daemon.modules.forEach((module_id) => {
|
||||
const module = all_modules.find((mod) => mod.id === module_id)
|
||||
Object.keys(ReZygiskState.rezygiskd).forEach((daemon_bit) => {
|
||||
const daemon = ReZygiskState.rezygiskd[daemon_bit]
|
||||
|
||||
if (module) {
|
||||
module.bitsUsed.push(daemon.bits)
|
||||
} else {
|
||||
all_modules.push({
|
||||
id: module_id,
|
||||
name: null,
|
||||
bitsUsed: [ daemon.bits ]
|
||||
})
|
||||
}
|
||||
})
|
||||
if (daemon.modules && daemon.modules.length > 0) {
|
||||
daemon.modules.forEach((module_id) => {
|
||||
const module = all_modules.find((mod) => mod.id === module_id)
|
||||
if (module) {
|
||||
module.bitsUsed.push(daemon_bit)
|
||||
} else {
|
||||
all_modules.push({
|
||||
id: module_id,
|
||||
name: null,
|
||||
bitsUsed: [ daemon_bit ]
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (all_modules.length !== 0) {
|
||||
@@ -251,7 +256,6 @@ async function getModuleNames(modules) {
|
||||
loading_screen.style.display = 'none'
|
||||
bottom_nav.style.display = 'flex'
|
||||
|
||||
|
||||
const start_time = Number(localStorage.getItem('/system/boot-time'))
|
||||
console.log('[rezygisk.js] boot time: ', Date.now() - start_time, 'ms')
|
||||
localStorage.removeItem('/system/boot_time')
|
||||
|
||||
@@ -261,11 +261,6 @@ static int spawn_companion(char *restrict argv[], char *restrict name, int lib_f
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct __attribute__((__packed__)) MsgHead {
|
||||
unsigned int cmd;
|
||||
int length;
|
||||
};
|
||||
|
||||
/* WARNING: Dynamic memory based */
|
||||
void zygiskd_start(char *restrict argv[]) {
|
||||
/* INFO: When implementation is None or Multiple, it won't set the values
|
||||
@@ -276,118 +271,42 @@ void zygiskd_start(char *restrict argv[]) {
|
||||
struct root_impl impl;
|
||||
get_impl(&impl);
|
||||
if (impl.impl == None || impl.impl == Multiple) {
|
||||
char *msg_data = NULL;
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &(uint8_t){ DAEMON_SET_ERROR_INFO }, sizeof(uint8_t));
|
||||
|
||||
if (impl.impl == None) msg_data = "Unsupported environment: Unknown root implementation";
|
||||
else msg_data = "Unsupported environment: Multiple root implementations found";
|
||||
const char *msg = NULL;
|
||||
if (impl.impl == None) msg = "Unsupported environment: Unknown root implementation";
|
||||
else msg = "Unsupported environment: Multiple root implementations found";
|
||||
|
||||
struct MsgHead msg = {
|
||||
.cmd = DAEMON_SET_ERROR_INFO,
|
||||
.length = (int)strlen(msg_data) + 1
|
||||
};
|
||||
LOGE("%s", msg);
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, msg_data, (size_t)msg.length);
|
||||
uint32_t msg_len = (uint32_t)strlen(msg);
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg_len, sizeof(msg_len));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, msg_len);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
enum Architecture arch = get_arch();
|
||||
load_modules(arch, &context);
|
||||
|
||||
char *module_list = NULL;
|
||||
size_t module_list_len = 0;
|
||||
if (context.len == 0) {
|
||||
module_list = strdup("None");
|
||||
module_list_len = strlen("None");
|
||||
} else {
|
||||
for (size_t i = 0; i < context.len; i++) {
|
||||
if (i != context.len - 1) {
|
||||
char *tmp_module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + strlen(", ") + 1);
|
||||
if (tmp_module_list == NULL) {
|
||||
LOGE("Failed reallocating memory for module list.\n");
|
||||
|
||||
char *kmsg_failure = "Failed reallocating memory for module list";
|
||||
struct MsgHead msg = {
|
||||
.cmd = DAEMON_SET_ERROR_INFO,
|
||||
.length = (int)strlen(kmsg_failure) + 1
|
||||
};
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, kmsg_failure, (size_t)msg.length);
|
||||
|
||||
free(module_list);
|
||||
free_modules(&context);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
module_list = tmp_module_list;
|
||||
|
||||
strcpy(module_list + module_list_len, context.modules[i].name);
|
||||
|
||||
module_list_len += strlen(context.modules[i].name);
|
||||
|
||||
strcpy(module_list + module_list_len, ", ");
|
||||
|
||||
module_list_len += strlen(", ");
|
||||
} else {
|
||||
char *tmp_module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + 1);
|
||||
if (tmp_module_list == NULL) {
|
||||
LOGE("Failed reallocating memory for module list.\n");
|
||||
|
||||
char *kmsg_failure = "Failed reallocating memory for module list";
|
||||
struct MsgHead msg = {
|
||||
.cmd = DAEMON_SET_ERROR_INFO,
|
||||
.length = (int)strlen(kmsg_failure) + 1
|
||||
};
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, kmsg_failure, (size_t)msg.length);
|
||||
|
||||
free(module_list);
|
||||
free_modules(&context);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
module_list = tmp_module_list;
|
||||
|
||||
strcpy(module_list + module_list_len, context.modules[i].name);
|
||||
|
||||
module_list_len += strlen(context.modules[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &(uint8_t){ DAEMON_SET_INFO }, sizeof(uint8_t));
|
||||
|
||||
char impl_name[LONGEST_ROOT_IMPL_NAME];
|
||||
stringify_root_impl_name(impl, impl_name);
|
||||
|
||||
size_t msg_length = strlen("Root: , Modules: ") + strlen(impl_name) + module_list_len + 1;
|
||||
uint32_t root_impl_len = (uint32_t)strlen(impl_name);
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &root_impl_len, sizeof(root_impl_len));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, impl_name, root_impl_len);
|
||||
|
||||
struct MsgHead msg = {
|
||||
.cmd = DAEMON_SET_INFO,
|
||||
.length = (int)msg_length
|
||||
};
|
||||
uint32_t modules_len = (uint32_t)context.len;
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &modules_len, sizeof(modules_len));
|
||||
|
||||
char *msg_data = malloc(msg_length);
|
||||
if (msg_data == NULL) {
|
||||
LOGE("Failed allocating memory for message data.\n");
|
||||
|
||||
char *kmsg_failure = "Failed allocating memory for message data";
|
||||
msg.cmd = DAEMON_SET_ERROR_INFO;
|
||||
msg.length = (int)strlen(kmsg_failure) + 1;
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, kmsg_failure, (size_t)msg.length);
|
||||
|
||||
free(module_list);
|
||||
free_modules(&context);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
for (size_t i = 0; i < context.len; i++) {
|
||||
uint32_t module_name_len = (uint32_t)strlen(context.modules[i].name);
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &module_name_len, sizeof(module_name_len));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, context.modules[i].name, module_name_len);
|
||||
}
|
||||
|
||||
snprintf(msg_data, msg_length, "Root: %s, Modules: %s", impl_name, module_list);
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, msg_data, msg_length);
|
||||
|
||||
free(msg_data);
|
||||
free(module_list);
|
||||
LOGI("Sent root implementation and modules information to controller socket");
|
||||
}
|
||||
|
||||
int socket_fd = create_daemon_socket();
|
||||
@@ -427,12 +346,7 @@ void zygiskd_start(char *restrict argv[]) {
|
||||
|
||||
switch (action) {
|
||||
case PingHeartbeat: {
|
||||
struct MsgHead msg = {
|
||||
.cmd = ZYGOTE_INJECTED,
|
||||
.length = 0
|
||||
};
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &(uint8_t){ ZYGOTE_INJECTED }, sizeof(uint8_t));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -447,22 +361,7 @@ void zygiskd_start(char *restrict argv[]) {
|
||||
break;
|
||||
}
|
||||
case SystemServerStarted: {
|
||||
struct MsgHead msg = {
|
||||
.cmd = SYSTEM_SERVER_STARTED,
|
||||
.length = 0
|
||||
};
|
||||
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead));
|
||||
|
||||
if (impl.impl == None || impl.impl == Multiple) {
|
||||
LOGI("Unsupported environment detected. Exiting.\n");
|
||||
|
||||
close(client_fd);
|
||||
close(socket_fd);
|
||||
free_modules(&context);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
unix_datagram_sendto(CONTROLLER_SOCKET, &(uint8_t){ SYSTEM_SERVER_STARTED }, sizeof(uint8_t));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user