diff --git a/loader/src/ptracer/monitor.c b/loader/src/ptracer/monitor.c index 7edb81f..e6e8f8d 100644 --- a/loader/src/ptracer/monitor.c +++ b/loader/src/ptracer/monitor.c @@ -48,10 +48,20 @@ struct rezygiskd_status { }; struct rezygiskd_status status64 = { - .daemon_pid = -1 + .supported = false, + .zygote_injected = false, + .daemon_running = false, + .daemon_pid = -1, + .daemon_info = NULL, + .daemon_error_info = NULL }; struct rezygiskd_status status32 = { - .daemon_pid = -1 + .supported = false, + .zygote_injected = false, + .daemon_running = false, + .daemon_pid = -1, + .daemon_info = NULL, + .daemon_error_info = NULL }; int monitor_epoll_fd; @@ -156,64 +166,51 @@ bool rezygiskd_listener_init() { return true; } +struct __attribute__((__packed__)) MsgHead { + unsigned int cmd; + int length; +}; + void rezygiskd_listener_callback() { - struct [[gnu::packed]] MsgHead { - enum rezygiskd_command cmd; - int length; - char data[0]; - }; - while (1) { - struct MsgHead *msg = (struct MsgHead *)malloc(sizeof(struct MsgHead)); + struct MsgHead msg = { 0 }; - ssize_t real_size; - ssize_t nread = recv(monitor_sock_fd, msg, sizeof(struct MsgHead), MSG_PEEK); - if (nread == -1) { - if (errno == EAGAIN) break; + size_t nread; - PLOGE("read socket"); - } + again: + nread = read(monitor_sock_fd, &msg, sizeof(msg)); + if ((int)nread == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) goto again; - if ((size_t)nread < sizeof(enum rezygiskd_command)) { - LOGE("read %zu < %zu", nread, sizeof(enum rezygiskd_command)); - continue; - } - - if (msg->cmd >= DAEMON64_SET_INFO && msg->cmd != SYSTEM_SERVER_STARTED) { - if (nread != sizeof(msg)) { - LOGE("cmd %d size %zu != %zu", msg->cmd, nread, sizeof(struct MsgHead)); + PLOGE("read socket"); continue; } - real_size = sizeof(struct MsgHead) + msg->length; - } else { - if (nread != sizeof(enum rezygiskd_command)) { - LOGE("cmd %d size %zu != %zu", msg->cmd, nread, sizeof(enum rezygiskd_command)); + char *msg_data = NULL; + + if (msg.length != 0) { + msg_data = malloc(msg.length); + if (!msg_data) { + LOGE("malloc msg data failed"); continue; } - real_size = sizeof(enum rezygiskd_command); + 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; + } } - msg = (struct MsgHead *)realloc(msg, real_size); - nread = recv(monitor_sock_fd, msg, real_size, 0); - - if (nread == -1) { - if (errno == EAGAIN) break; - - PLOGE("recv"); - continue; - } - - if (nread != real_size) { - LOGE("real size %zu != %zu", real_size, nread); - - continue; - } - - switch (msg->cmd) { + switch (msg.cmd) { case START: { if (tracing_state == STOPPING) tracing_state = TRACING; else if (tracing_state == STOPPED) { @@ -267,7 +264,7 @@ void rezygiskd_listener_callback() { break; } case DAEMON64_SET_INFO: { - LOGD("received daemon64 info %s", msg->data); + LOGD("received daemon64 info %s", msg_data); /* Will only happen if somehow the daemon restarts */ if (status64.daemon_info) { @@ -275,42 +272,42 @@ void rezygiskd_listener_callback() { status64.daemon_info = NULL; } - status64.daemon_info = (char *)malloc(msg->length); + status64.daemon_info = (char *)malloc(msg.length); if (!status64.daemon_info) { PLOGE("malloc daemon64 info"); break; } - strcpy(status64.daemon_info, msg->data); + strcpy(status64.daemon_info, msg_data); update_status(NULL); break; } case DAEMON32_SET_INFO: { - LOGD("received daemon32 info %s", msg->data); + LOGD("received daemon32 info %s", msg_data); if (status32.daemon_info) { free(status32.daemon_info); status32.daemon_info = NULL; } - status32.daemon_info = (char *)malloc(msg->length); + status32.daemon_info = (char *)malloc(msg.length); if (!status32.daemon_info) { PLOGE("malloc daemon32 info"); break; } - strcpy(status32.daemon_info, msg->data); + strcpy(status32.daemon_info, msg_data); update_status(NULL); break; } case DAEMON64_SET_ERROR_INFO: { - LOGD("received daemon64 error info %s", msg->data); + LOGD("received daemon64 error info %s", msg_data); status64.daemon_running = false; @@ -319,21 +316,21 @@ void rezygiskd_listener_callback() { status64.daemon_error_info = NULL; } - status64.daemon_error_info = (char *)malloc(msg->length); + status64.daemon_error_info = (char *)malloc(msg.length); if (!status64.daemon_error_info) { PLOGE("malloc daemon64 error info"); break; } - strcpy(status64.daemon_error_info, msg->data); + strcpy(status64.daemon_error_info, msg_data); update_status(NULL); break; } case DAEMON32_SET_ERROR_INFO: { - LOGD("received daemon32 error info %s", msg->data); + LOGD("received daemon32 error info %s", msg_data); status32.daemon_running = false; @@ -342,14 +339,14 @@ void rezygiskd_listener_callback() { status32.daemon_error_info = NULL; } - status32.daemon_error_info = (char *)malloc(msg->length); + status32.daemon_error_info = (char *)malloc(msg.length); if (!status32.daemon_error_info) { PLOGE("malloc daemon32 error info"); break; } - strcpy(status32.daemon_error_info, msg->data); + strcpy(status32.daemon_error_info, msg_data); update_status(NULL); @@ -366,7 +363,9 @@ void rezygiskd_listener_callback() { } } - free(msg); + if (msg_data) free(msg_data); + + break; } } @@ -402,39 +401,42 @@ CREATE_ZYGOTE_START_COUNTER(32) static bool ensure_daemon_created(bool is_64bit) { struct rezygiskd_status *status = is_64bit ? &status64 : &status32; - if (is_64bit) { + + if (is_64bit || (!is_64bit && !status64.supported)) { LOGD("new zygote started."); umount2("/data/adb/modules/zygisksu/module.prop", MNT_DETACH); } - status->zygote_injected = false; + if (status->daemon_pid != -1) { + LOGI("daemon%s already running", is_64bit ? "64" : "32"); - if (status->daemon_pid == -1) { - pid_t pid = fork(); - if (pid < 0) { - PLOGE("create daemon%s", is_64bit ? "64" : "32"); - - return false; - } else if (pid == 0) { - char daemon_name[PATH_MAX] = "./bin/zygiskd"; - strcat(daemon_name, is_64bit ? "64" : "32"); - - execl(daemon_name, daemon_name, NULL); - - PLOGE("exec daemon %s failed", daemon_name); - - exit(1); - } else { - status->supported = true; - status->daemon_pid = pid; - status->daemon_running = true; - - return true; - } - } else { return status->daemon_running; } + + pid_t pid = fork(); + if (pid < 0) { + PLOGE("create daemon%s", is_64bit ? "64" : "32"); + + return false; + } + + if (pid == 0) { + char daemon_name[PATH_MAX] = "./bin/zygiskd"; + strcat(daemon_name, is_64bit ? "64" : "32"); + + execl(daemon_name, daemon_name, NULL); + + PLOGE("exec daemon %s failed", daemon_name); + + exit(1); + } + + status->supported = true; + status->daemon_pid = pid; + status->daemon_running = true; + + return true; } #define CHECK_DAEMON_EXIT(abi) \ @@ -845,20 +847,33 @@ void init_monitor() { monitor_events_init(); - rezygiskd_listener_init(); - struct monitor_event_cbs listener_cbs = { .callback = rezygiskd_listener_callback, .stop_callback = rezygiskd_listener_stop }; - monitor_events_register_event(&listener_cbs, monitor_sock_fd, EPOLLIN | EPOLLET); + if (!rezygiskd_listener_init()) { + LOGE("failed to create socket"); - sigchld_listener_init(); + close(monitor_epoll_fd); + + exit(1); + } + + monitor_events_register_event(&listener_cbs, monitor_sock_fd, EPOLLIN | EPOLLET); struct monitor_event_cbs sigchld_cbs = { .callback = sigchld_listener_callback, .stop_callback = sigchld_listener_stop }; + if (sigchld_listener_init() == false) { + LOGE("failed to create signalfd"); + + rezygiskd_listener_stop(); + close(monitor_epoll_fd); + + exit(1); + } + monitor_events_register_event(&sigchld_cbs, sigchld_signal_fd, EPOLLIN | EPOLLET); monitor_events_loop(); diff --git a/module/src/customize.sh b/module/src/customize.sh index 649b707..f1e113f 100644 --- a/module/src/customize.sh +++ b/module/src/customize.sh @@ -107,40 +107,69 @@ extract "$ZIPFILE" 'uninstall.sh' "$MODPATH" mv "$TMPDIR/sepolicy.rule" "$MODPATH" mkdir "$MODPATH/bin" -mkdir "$MODPATH/lib" -mkdir "$MODPATH/lib64" + +CPU_ABIS=$(getprop ro.product.cpu.abilist) + +SUPPORTS_32BIT=false +SUPPORTS_64BIT=false + +if [[ "$CPU_ABIS" == *"x86"* && "$CPU_ABIS" != "x86_64" || "$CPU_ABIS" == *"armeabi"* ]]; then + SUPPORTS_32BIT=true + ui_print "- Device supports 32-bit" +fi + +if [[ "$CPU_ABIS" == *"x86_64"* || "$CPU_ABIS" == *"arm64-v8a"* ]]; then + SUPPORTS_64BIT=true + ui_print "- Device supports 64-bit" +fi + +if [ "$SUPPORTS_32BIT" = true ]; then + mkdir "$MODPATH/lib" +fi + +if [ "$SUPPORTS_64BIT" = true ]; then + mkdir "$MODPATH/lib64" +fi if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then - ui_print "- Extracting x86 libraries" - extract "$ZIPFILE" 'bin/x86/zygiskd' "$MODPATH/bin" true - mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32" - extract "$ZIPFILE" 'lib/x86/libzygisk.so' "$MODPATH/lib" true - extract "$ZIPFILE" 'lib/x86/libzygisk_ptrace.so' "$MODPATH/bin" true - mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace32" + if [ "$SUPPORTS_32BIT" = true ]; then + ui_print "- Extracting x86 libraries" + extract "$ZIPFILE" 'bin/x86/zygiskd' "$MODPATH/bin" true + mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32" + extract "$ZIPFILE" 'lib/x86/libzygisk.so' "$MODPATH/lib" true + extract "$ZIPFILE" 'lib/x86/libzygisk_ptrace.so' "$MODPATH/bin" true + mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace32" + fi - ui_print "- Extracting x64 libraries" - extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true - mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64" - extract "$ZIPFILE" 'lib/x86_64/libzygisk.so' "$MODPATH/lib64" true - extract "$ZIPFILE" 'lib/x86_64/libzygisk_ptrace.so' "$MODPATH/bin" true - mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace64" + if [ "$SUPPORTS_64BIT" = true ]; then + ui_print "- Extracting x64 libraries" + extract "$ZIPFILE" 'bin/x86_64/zygiskd' "$MODPATH/bin" true + mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64" + extract "$ZIPFILE" 'lib/x86_64/libzygisk.so' "$MODPATH/lib64" true + extract "$ZIPFILE" 'lib/x86_64/libzygisk_ptrace.so' "$MODPATH/bin" true + mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace64" + fi extract "$ZIPFILE" 'machikado.x86' "$MODPATH" true mv "$MODPATH/machikado.x86" "$MODPATH/machikado" else - ui_print "- Extracting arm libraries" - extract "$ZIPFILE" 'bin/armeabi-v7a/zygiskd' "$MODPATH/bin" true - mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32" - extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk.so' "$MODPATH/lib" true - extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk_ptrace.so' "$MODPATH/bin" true - mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace32" + if [ "$SUPPORTS_32BIT" = true ]; then + ui_print "- Extracting arm libraries" + extract "$ZIPFILE" 'bin/armeabi-v7a/zygiskd' "$MODPATH/bin" true + mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd32" + extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk.so' "$MODPATH/lib" true + extract "$ZIPFILE" 'lib/armeabi-v7a/libzygisk_ptrace.so' "$MODPATH/bin" true + mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace32" + fi - ui_print "- Extracting arm64 libraries" - extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true - mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64" - extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk.so' "$MODPATH/lib64" true - extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk_ptrace.so' "$MODPATH/bin" true - mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace64" + if [ "$SUPPORTS_64BIT" = true ]; then + ui_print "- Extracting arm64 libraries" + extract "$ZIPFILE" 'bin/arm64-v8a/zygiskd' "$MODPATH/bin" true + mv "$MODPATH/bin/zygiskd" "$MODPATH/bin/zygiskd64" + extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk.so' "$MODPATH/lib64" true + extract "$ZIPFILE" 'lib/arm64-v8a/libzygisk_ptrace.so' "$MODPATH/bin" true + mv "$MODPATH/bin/libzygisk_ptrace.so" "$MODPATH/bin/zygisk-ptrace64" + fi extract "$ZIPFILE" 'machikado.arm' "$MODPATH" true mv "$MODPATH/machikado.arm" "$MODPATH/machikado" @@ -148,8 +177,14 @@ fi ui_print "- Setting permissions" set_perm_recursive "$MODPATH/bin" 0 0 0755 0755 -set_perm_recursive "$MODPATH/lib" 0 0 0755 0644 u:object_r:system_lib_file:s0 -set_perm_recursive "$MODPATH/lib64" 0 0 0755 0644 u:object_r:system_lib_file:s0 + +if [ "$SUPPORTS_32BIT" = true ]; then + set_perm_recursive "$MODPATH/lib" 0 0 0755 0644 u:object_r:system_lib_file:s0 +fi + +if [ "$SUPPORTS_64BIT" = true ]; then + set_perm_recursive "$MODPATH/lib64" 0 0 0755 0644 u:object_r:system_lib_file:s0 +fi # If Huawei's Maple is enabled, system_server is created with a special way which is out of Zygisk's control HUAWEI_MAPLE_ENABLED=$(grep_prop ro.maple.enable) diff --git a/module/src/post-fs-data.sh b/module/src/post-fs-data.sh index 631fc48..7fa64e6 100644 --- a/module/src/post-fs-data.sh +++ b/module/src/post-fs-data.sh @@ -46,5 +46,12 @@ if [ -f $MODDIR/lib/libzygisk.so ];then chcon u:object_r:system_file:s0 $TMP_PATH/lib/libzygisk.so fi -[ "$DEBUG" = true ] && export RUST_BACKTRACE=1 -./bin/zygisk-ptrace64 monitor & +CPU_ABIS=$(getprop ro.product.cpu.abilist) + +if [[ "$CPU_ABIS" == *"arm64-v8a"* || "$CPU_ABIS" == *"x86_64"* ]]; then + ./bin/zygisk-ptrace64 monitor & +else + # INFO: Device is 32-bit only + + ./bin/zygisk-ptrace32 monitor & +fi diff --git a/module/src/sepolicy.rule b/module/src/sepolicy.rule index 76835a1..e2874f2 100644 --- a/module/src/sepolicy.rule +++ b/module/src/sepolicy.rule @@ -10,6 +10,7 @@ allow zygote su {lnk_file file} read allow zygote adb_data_file dir search allow zygote adb_data_file file * +allow zygote proc file {read open} allow zygote zygote process execmem allow system_server system_server process execmem allow zygote tmpfs file * diff --git a/zygiskd/src/zygiskd.c b/zygiskd/src/zygiskd.c index 3e18f6c..918b278 100644 --- a/zygiskd/src/zygiskd.c +++ b/zygiskd/src/zygiskd.c @@ -49,7 +49,7 @@ enum Architecture { static enum Architecture get_arch(void) { char system_arch[32]; - get_property("ro.product.cpu.abi", system_arch); + get_property("ro.product.cpu.abilist", system_arch); if (strstr(system_arch, "arm") != NULL) return lp_select(ARM32, ARM64); if (strstr(system_arch, "x86") != NULL) return lp_select(X86, X86_64); @@ -255,7 +255,6 @@ static int spawn_companion(char *restrict argv[], char *restrict name, int lib_f struct __attribute__((__packed__)) MsgHead { unsigned int cmd; int length; - char data[0]; }; /* WARNING: Dynamic memory based */ @@ -268,29 +267,20 @@ void zygiskd_start(char *restrict argv[]) { struct root_impl impl; get_impl(&impl); if (impl.impl == None || impl.impl == Multiple) { - struct MsgHead *msg = NULL; - - if (impl.impl == None) { - msg = malloc(sizeof(struct MsgHead) + strlen("Unsupported environment: Unknown root implementation") + 1); - } else { - msg = malloc(sizeof(struct MsgHead) + strlen("Unsupported environment: Multiple root implementations found") + 1); - } - if (msg == NULL) { - LOGE("Failed allocating memory for message.\n"); + char *msg_data = NULL; - return; - } + if (impl.impl == None) msg_data = "Unsupported environment: Unknown root implementation"; + else msg_data = "Unsupported environment: Multiple root implementations found"; - msg->cmd = DAEMON_SET_ERROR_INFO; - if (impl.impl == None) { - msg->length = sprintf(msg->data, "Unsupported environment: Unknown root implementation"); - } else { - msg->length = sprintf(msg->data, "Unsupported environment: Multiple root implementations found"); - } + struct MsgHead msg = { + .cmd = DAEMON_SET_ERROR_INFO, + .length = (int)strlen(msg_data) + 1 + }; - unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, (size_t)((int)sizeof(struct MsgHead) + msg->length)); + unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead)); + unix_datagram_sendto(CONTROLLER_SOCKET, msg_data, (size_t)msg.length); - free(msg); + free(msg_data); } else { enum Architecture arch = get_arch(); load_modules(arch, &context); @@ -337,13 +327,24 @@ void zygiskd_start(char *restrict argv[]) { size_t msg_length = strlen("Root: , Modules: ") + strlen(impl_name) + module_list_len + 1; - struct MsgHead *msg = malloc(sizeof(struct MsgHead) + msg_length); - msg->length = snprintf(msg->data, msg_length, "Root: %s, Modules: %s", impl_name, module_list) + 1; - msg->cmd = DAEMON_SET_INFO; + struct MsgHead msg = { + .cmd = DAEMON_SET_INFO, + .length = (int)msg_length + }; - unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, (size_t)((int)sizeof(struct MsgHead) + msg->length)); + char *msg_data = malloc(msg_length); + if (msg_data == NULL) { + LOGE("Failed allocating memory for message data.\n"); - free(msg); + return; + } + + 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); } @@ -379,8 +380,12 @@ void zygiskd_start(char *restrict argv[]) { switch (action) { case PingHeartbeat: { - enum DaemonSocketAction msgr = ZYGOTE_INJECTED; - unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + struct MsgHead msg = { + .cmd = ZYGOTE_INJECTED, + .length = 0 + }; + + unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead)); break; } @@ -395,8 +400,12 @@ void zygiskd_start(char *restrict argv[]) { break; } case SystemServerStarted: { - enum DaemonSocketAction msgr = SYSTEM_SERVER_STARTED; - unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + 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");