From c1e45e9af603dcd36df97323294a5358e0e17756 Mon Sep 17 00:00:00 2001 From: ThePedroo Date: Thu, 15 Aug 2024 22:42:47 -0300 Subject: [PATCH] add: zygiskd C99 APatch support This commit adds support for zygiskd C99 to recognize APatch rooted devices. --- zygiskd/build.gradle.kts | 14 +- zygiskd/src/companion.c | 31 +-- zygiskd/src/constants.h | 15 +- zygiskd/src/main.c | 15 +- zygiskd/src/root_impl/apatch.c | 144 ++++++++++++++ zygiskd/src/root_impl/apatch.h | 14 ++ zygiskd/src/root_impl/common.c | 62 +++--- zygiskd/src/root_impl/common.h | 5 +- zygiskd/src/root_impl/kernelsu.c | 24 +-- zygiskd/src/root_impl/kernelsu.h | 2 +- zygiskd/src/utils.c | 35 ++++ zygiskd/src/utils.h | 13 +- zygiskd/src/zygiskd.c | 320 +++++++++++++++++++------------ 13 files changed, 484 insertions(+), 210 deletions(-) create mode 100644 zygiskd/src/root_impl/apatch.c create mode 100644 zygiskd/src/root_impl/apatch.h diff --git a/zygiskd/build.gradle.kts b/zygiskd/build.gradle.kts index 341af93..62a0f64 100644 --- a/zygiskd/build.gradle.kts +++ b/zygiskd/build.gradle.kts @@ -14,7 +14,8 @@ fun getLatestNDKPath(): String { throw Exception("NDK not found at $ndkPath") } - val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().last() + // get 2nd latest version + val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(1) return ndkPath + "/" + ndkVersion } @@ -26,6 +27,14 @@ val verCode: Int by rootProject.extra val verName: String by rootProject.extra val commitHash: String by rootProject.extra +val CStandardFlags = arrayOf( + "-DMIN_APATCH_VERSION=$minAPatchVersion", + "-DMIN_KSU_VERSION=$minKsuVersion", + "-DMAX_KSU_VERSION=$maxKsuVersion", + "-DMIN_MAGISK_VERSION=$minMagiskVersion", + "-DZKSU_VERSION=\"$verName\"" +) + val CFlagsRelease = arrayOf( "-D_GNU_SOURCE", "-std=c99", "-Wpedantic", "-Wall", "-Wextra", "-Werror", "-Wformat", "-Wuninitialized", "-Wshadow", "-Wno-zero-length-array", @@ -41,6 +50,7 @@ val CFlagsDebug = arrayOf( ) val Files = arrayOf( + "root_impl/apatch.c", "root_impl/common.c", "root_impl/kernelsu.c", "companion.c", @@ -94,7 +104,7 @@ task("buildAndStrip") { x86OutputDir.mkdirs() x86_64OutputDir.mkdirs() - val compileArgs = if (isDebug) CFlagsDebug else CFlagsRelease + val compileArgs = (if (isDebug) CFlagsDebug else CFlagsRelease) + CStandardFlags exec { commandLine(aarch64Compiler, "-o", Paths.get(aarch64OutputDir.toString(), "zygiskd").toString(), *compileArgs, *Files) diff --git a/zygiskd/src/companion.c b/zygiskd/src/companion.c index b3b8442..c12337b 100644 --- a/zygiskd/src/companion.c +++ b/zygiskd/src/companion.c @@ -17,9 +17,9 @@ #include "dl.h" #include "utils.h" -typedef void (*ZygiskCompanionEntryFn)(int); +typedef void (*zygisk_companion_entry_func)(int); -ZygiskCompanionEntryFn load_module(int fd) { +zygisk_companion_entry_func load_module(int fd) { char path[PATH_MAX]; snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); @@ -27,10 +27,10 @@ ZygiskCompanionEntryFn load_module(int fd) { void *entry = dlsym(handle, "zygisk_companion_entry"); if (entry == NULL) return NULL; - return (ZygiskCompanionEntryFn)entry; + return (zygisk_companion_entry_func)entry; } -void *ExecuteNew(void *arg) { +void *call_entry(void *arg) { int fd = *((int *)arg); struct stat st0; @@ -65,13 +65,10 @@ void *ExecuteNew(void *arg) { return NULL; } - void entry(int fd) { LOGI("companion entry fd: |%d|\n", fd); char name[256 + 1]; - - /* INFO: Getting stuck here */ ssize_t ret = read_string(fd, name, sizeof(name) - 1); if (ret == -1) return; @@ -84,7 +81,7 @@ void entry(int fd) { LOGI("Library fd: %d\n", library_fd); - ZygiskCompanionEntryFn entry = load_module(library_fd); + zygisk_companion_entry_func entry = load_module(library_fd); LOGI("Library loaded\n"); @@ -95,17 +92,28 @@ void entry(int fd) { if (entry == NULL) { LOGI("No companion entry for: %s\n", name); - write(fd, (void *)0, 1); + uint8_t response[1] = { 0 }; + write(fd, &response, sizeof(response)); + + exit(0); return; } LOGI("Companion process created for: %s\n", name); - uint8_t response = 1; + uint8_t response[1] = { 1 }; write(fd, &response, sizeof(response)); while (1) { + if (!check_unix_socket(fd, true)) { + LOGI("Something went wrong. Bye!\n"); + + exit(0); + + break; + } + int client_fd; recv_fd(fd, &client_fd); @@ -113,13 +121,14 @@ void entry(int fd) { write(fd, &response, sizeof(response)); + /* TODO: Do we really need to allocate this..? */ int *client_fd_ptr = malloc(sizeof(int)); *client_fd_ptr = client_fd; LOGI("Creating new thread for companion request\n"); pthread_t thread; - pthread_create(&thread, NULL, ExecuteNew, (void *)client_fd_ptr); + pthread_create(&thread, NULL, call_entry, (void *)client_fd_ptr); pthread_detach(thread); } } diff --git a/zygiskd/src/constants.h b/zygiskd/src/constants.h index 94a7f5a..55f8a56 100644 --- a/zygiskd/src/constants.h +++ b/zygiskd/src/constants.h @@ -7,20 +7,6 @@ #define true 1 #define false 0 -// #define MIN_APATCH_VERSION (atoi(getenv("MIN_APATCH_VERSION"))) -// #define MIN_KSU_VERSION (atoi(getenv("MIN_KSU_VERSION"))) -// #define MAX_KSU_VERSION (atoi(getenv("MAX_KSU_VERSION"))) -// #define MIN_MAGISK_VERSION (atoi(getenv("MIN_MAGISK_VERSION"))) -// #define ZKSU_VERSION (getenv("ZKSU_VERSION")) - -#define MIN_APATCH_VERSION 0 -// val minKsudVersion by extra(11425) -// val maxKsuVersion by extra(20000) -#define MIN_KSU_VERSION 11425 -#define MAX_KSU_VERSION 20000 -#define MIN_MAGISK_VERSION 0 -#define ZKSU_VERSION "1.0.0" - #if DEBUG == false #define MAX_LOG_LEVEL ANDROID_LOG_VERBOSE #else @@ -64,6 +50,7 @@ enum ProcessFlags: uint32_t { enum RootImplState { Supported, TooOld, + Inexistent, Abnormal }; diff --git a/zygiskd/src/main.c b/zygiskd/src/main.c index c551dde..b7b9d86 100644 --- a/zygiskd/src/main.c +++ b/zygiskd/src/main.c @@ -14,14 +14,7 @@ int __android_log_print(int prio, const char *tag, const char *fmt, ...); int main(int argc, char *argv[]) { - errno = 0; - /* Initialize android logger */ - LOGI("Initializing zygiskd\n"); - - LOGI("Argc: %d\n", argc); - for (int i = 0; i < argc; i++) { - LOGI("argv[%d] = %s\n", i, argv[i]); - } + LOGI("Initializing zygiskd: %s\n", argv[0]); if (argc > 1) { if (strcmp(argv[1], "companion") == 0) { @@ -63,10 +56,14 @@ int main(int argc, char *argv[]) { case KernelSU: { LOGI("KernelSU root implementation found.\n"); + return 0; + } + case APatch: { + LOGI("APatch root implementation found.\n"); + return 0; } } - return 0; } diff --git a/zygiskd/src/root_impl/apatch.c b/zygiskd/src/root_impl/apatch.c new file mode 100644 index 0000000..e43ca4f --- /dev/null +++ b/zygiskd/src/root_impl/apatch.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include + +#include "../constants.h" +#include "../utils.h" + +#include "apatch.h" + +enum RootImplState apatch_get_existence(void) { + struct stat s; + if (stat("/data/adb/apd", &s) != 0) { + LOGE("APATCH | Failed to stat /data/adb/apd: %s\n", strerror(errno)); + + return Inexistent; + } + + char apatch_version[32]; + char *const argv[] = { "apd", "-V", NULL }; + + LOGI("APATCH | Checking for apd existence\n"); + if (!exec_command(apatch_version, sizeof(apatch_version), "/data/adb/apd", argv)) { + LOGE("APATCH | Failed to execute apd binary: %s\n", strerror(errno)); + errno = 0; + + return Inexistent; + } + + int version = atoi(apatch_version + strlen("apd ")); + LOGI("APATCH | apd version: %d\n", version); + if (version == 0) return Abnormal; + + if (version >= MIN_APATCH_VERSION && version <= 999999) return Supported; + if (version >= 1 && version <= MIN_APATCH_VERSION - 1) return TooOld; + + return Inexistent; +} + +struct package_config { + uid_t uid; + bool root_granted; + bool umount_needed; +}; + +struct packages_config { + struct package_config *configs; + size_t size; +}; + +bool _apatch_get_package_config(struct packages_config *config) { + FILE *fp = fopen("/data/adb/ap/package_config", "r"); + if (fp == NULL) { + LOGE("APATCH | Failed to open package_config: %s\n", strerror(errno)); + + return false; + } + + char line[256]; + /* INFO: Skip the CSV header */ + fgets(line, sizeof(line), fp); + + while (fgets(line, sizeof(line), fp) != NULL) { + config->configs = realloc(config, (config->size + 1) * sizeof(struct package_config)); + if (config->configs == NULL) { + LOGE("APATCH | Failed to realloc package config: %s\n", strerror(errno)); + + fclose(fp); + + return false; + } + + strtok(line, ","); + + char *exclude_str = strtok(NULL, ","); + if (exclude_str == NULL) continue; + + char *allow_str = strtok(NULL, ","); + if (allow_str == NULL) continue; + + char *uid_str = strtok(NULL, ","); + if (uid_str == NULL) continue; + + config->configs[config->size].uid = atoi(uid_str); + config->configs[config->size].root_granted = strcmp(allow_str, "1") == 0; + config->configs[config->size].umount_needed = strcmp(exclude_str, "1") == 0; + + config->size++; + } + + fclose(fp); + + return true; +} + +bool apatch_uid_granted_root(uid_t uid) { + struct packages_config *config = NULL; + if (!_apatch_get_package_config(config)) { + free(config); + + return false; + } + + for (size_t i = 0; i < config->size; i++) { + if (config->configs[i].uid == uid) { + free(config); + + return config->configs[i].root_granted; + } + } + + free(config); + + return false; +} + +bool apatch_uid_should_umount(uid_t uid) { + struct packages_config *config = NULL; + if (!_apatch_get_package_config(config)) { + free(config); + + return false; + } + + for (size_t i = 0; i < config->size; i++) { + if (config->configs[i].uid == uid) { + free(config); + + return config->configs[i].umount_needed; + } + } + + free(config); + + return false; +} + +bool apatch_uid_is_manager(uid_t uid) { + struct stat s; + if (stat("/data/user_de/0/me.bmax.apatch", &s) == -1) return false; + + return s.st_uid == uid; +} diff --git a/zygiskd/src/root_impl/apatch.h b/zygiskd/src/root_impl/apatch.h new file mode 100644 index 0000000..e45fc17 --- /dev/null +++ b/zygiskd/src/root_impl/apatch.h @@ -0,0 +1,14 @@ +#ifndef APATCH_H +#define APATCH_H + +#include "../constants.h" + +enum RootImplState apatch_get_existence(void); + +bool apatch_uid_granted_root(uid_t uid); + +bool apatch_uid_should_umount(uid_t uid); + +bool apatch_uid_is_manager(uid_t uid); + +#endif diff --git a/zygiskd/src/root_impl/common.c b/zygiskd/src/root_impl/common.c index ddc75c1..d319430 100644 --- a/zygiskd/src/root_impl/common.c +++ b/zygiskd/src/root_impl/common.c @@ -1,19 +1,16 @@ #include #include "kernelsu.h" +#include "apatch.h" #include "common.h" static enum RootImpl ROOT_IMPL = None; void root_impls_setup(void) { - enum RootImplState ksu_version = ksu_get_kernel_su(); - - enum RootImpl impl = None; - - if (ksu_version == Supported) impl = KernelSU; - - ROOT_IMPL = impl; + if (ksu_get_existence() == Supported) ROOT_IMPL = KernelSU; + else if (apatch_get_existence() == Supported) ROOT_IMPL = APatch; + else ROOT_IMPL = None; } enum RootImpl get_impl(void) { @@ -21,34 +18,43 @@ enum RootImpl get_impl(void) { } bool uid_granted_root(uid_t uid) { - switch (get_impl()) { - case KernelSU: { + // switch (get_impl()) { + // case KernelSU: { return ksu_uid_granted_root(uid); - } - default: { - return false; - } - } + // } + // case APatch: { + // return apatch_uid_granted_root(uid); + // } + // default: { + // return false; + // } + // } } bool uid_should_umount(uid_t uid) { - switch (get_impl()) { - case KernelSU: { + // switch (get_impl()) { + // case KernelSU: { return ksu_uid_should_umount(uid); - } - default: { - return false; - } - } + // } + // case APatch: { + // return apatch_uid_should_umount(uid); + // } + // default: { + // return false; + // } + // } } bool uid_is_manager(uid_t uid) { - switch (get_impl()) { - case KernelSU: { + // switch (get_impl()) { + // case KernelSU: { return ksu_uid_is_manager(uid); - } - default: { - return false; - } - } + // } + // case APatch: { + // return apatch_uid_is_manager(uid); + // } + // default: { + // return false; + // } + // } } diff --git a/zygiskd/src/root_impl/common.h b/zygiskd/src/root_impl/common.h index 314caf3..79964f1 100644 --- a/zygiskd/src/root_impl/common.h +++ b/zygiskd/src/root_impl/common.h @@ -5,8 +5,9 @@ enum RootImpl { None, - Multiple, /* INFO: I know. */ - KernelSU + Multiple, + KernelSU, + APatch }; void root_impls_setup(void); diff --git a/zygiskd/src/root_impl/kernelsu.c b/zygiskd/src/root_impl/kernelsu.c index b8f950c..853b494 100644 --- a/zygiskd/src/root_impl/kernelsu.c +++ b/zygiskd/src/root_impl/kernelsu.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -14,16 +15,12 @@ #define CMD_UID_GRANTED_ROOT 12 #define CMD_UID_SHOULD_UMOUNT 13 -enum RootImplState ksu_get_kernel_su(void) { +enum RootImplState ksu_get_existence(void) { int version = 0; prctl(KERNEL_SU_OPTION, CMD_GET_VERSION, &version, 0, 0); - errno = 0; - - if (version == 0) return Abnormal; - + if (version == 0) return Inexistent; if (version >= MIN_KSU_VERSION && version <= MAX_KSU_VERSION) return Supported; - if (version >= 1 && version <= MIN_KSU_VERSION - 1) return TooOld; return Abnormal; @@ -34,8 +31,6 @@ bool ksu_uid_granted_root(uid_t uid) { bool granted = false; prctl(KERNEL_SU_OPTION, CMD_UID_GRANTED_ROOT, uid, &granted, &result); - LOGI("ksu_uid_granted_root: %d", granted); - if (result != KERNEL_SU_OPTION) return false; return granted; @@ -46,23 +41,14 @@ bool ksu_uid_should_umount(uid_t uid) { bool umount = false; prctl(KERNEL_SU_OPTION, CMD_UID_SHOULD_UMOUNT, uid, &umount, &result); - LOGI("ksu_uid_should_umount: %d", umount); - if (result != KERNEL_SU_OPTION) return false; return umount; } bool ksu_uid_is_manager(uid_t uid) { - struct stat s; - if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == 0) { - LOGI("ksu_uid_is_manager: %d", uid); + if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) return false; - return s.st_uid == uid; - } - - LOGI("ksu_uid_is_manager: false"); - - return false; + return s.st_uid == uid; } diff --git a/zygiskd/src/root_impl/kernelsu.h b/zygiskd/src/root_impl/kernelsu.h index 1f2c494..83d01bb 100644 --- a/zygiskd/src/root_impl/kernelsu.h +++ b/zygiskd/src/root_impl/kernelsu.h @@ -3,7 +3,7 @@ #include "../constants.h" -enum RootImplState ksu_get_kernel_su(void); +enum RootImplState ksu_get_existence(void); bool ksu_uid_granted_root(uid_t uid); diff --git a/zygiskd/src/utils.c b/zygiskd/src/utils.c index d5f9cec..141c3f8 100644 --- a/zygiskd/src/utils.c +++ b/zygiskd/src/utils.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -280,3 +281,37 @@ ssize_t read_string(int fd, char *str, size_t len) { return read_bytes; } + +bool exec_command(char *buf, size_t len, const char *file, char *const argv[]) { + int link[2]; + pid_t pid; + + if (pipe(link) == -1) { + LOGE("pipe: %s\n", strerror(errno)); + + return false; + } + + if ((pid = fork()) == -1) { + LOGE("fork: %s\n", strerror(errno)); + + return false; + } + + if (pid == 0) { + dup2(link[1], STDOUT_FILENO); + close(link[0]); + close(link[1]); + + execv(file, argv); + } else { + close(link[1]); + + int nbytes = read(link[0], buf, len); + buf[nbytes] = '\0'; + + wait(NULL); + } + + return true; +} diff --git a/zygiskd/src/utils.h b/zygiskd/src/utils.h index 7362950..8d112ea 100644 --- a/zygiskd/src/utils.h +++ b/zygiskd/src/utils.h @@ -5,13 +5,18 @@ #include "constants.h" +#define CONCAT_(x,y) x##y +#define CONCAT(x,y) CONCAT_(x,y) + #define LOGI(...) \ __android_log_print(ANDROID_LOG_INFO, lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \ - printf(__VA_ARGS__) + printf(__VA_ARGS__); \ + FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__)) #define LOGE(...) \ __android_log_print(ANDROID_LOG_INFO , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \ - printf(__VA_ARGS__) + printf(__VA_ARGS__); \ + FILE *CONCAT(fpl, __LINE__) = fopen("/data/local/tmp/zygiskd.log", "a"); fprintf(CONCAT(fpl, __LINE__), __VA_ARGS__); fclose(CONCAT(fpl, __LINE__)) bool switch_mount_namespace(pid_t pid); @@ -33,4 +38,8 @@ ssize_t write_string(int fd, const char *str); ssize_t read_string(int fd, char *str, size_t len); +bool exec_command(char *buf, size_t len, const char *file, char *const argv[]); + +bool check_unix_socket(int fd, bool block); + #endif /* UTILS_H */ diff --git a/zygiskd/src/zygiskd.c b/zygiskd/src/zygiskd.c index 311bf06..45f04b1 100644 --- a/zygiskd/src/zygiskd.c +++ b/zygiskd/src/zygiskd.c @@ -41,7 +41,7 @@ enum Architecture { #define TMP_PATH "/data/adb/rezygisk" #define CONTROLLER_SOCKET TMP_PATH "/init_monitor" #define PATH_CP_NAME TMP_PATH "/" lp_select("cp32.sock", "cp64.sock") -#define ZYGISKD_FILE "zygiskd" lp_select("32", "64") +#define ZYGISKD_FILE PATH_MODULES_DIR "/zygisksu/bin/zygiskd" lp_select("32", "64") #define ZYGISKD_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64") #define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \ @@ -100,30 +100,42 @@ static enum Architecture get_arch(void) { int create_library_fd(const char *so_path) { int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING); if (memfd == -1) { - perror("memfd_create"); + LOGE("Failed creating memfd: %s\n", strerror(errno)); return -1; } int so_fd = open(so_path, O_RDONLY); if (so_fd == -1) { - perror("open"); + LOGE("Failed opening so file: %s\n", strerror(errno)); + close(memfd); return -1; } - struct stat st; - if (fstat(so_fd, &st) == -1) { - perror("fstat"); + off_t so_size = lseek(so_fd, 0, SEEK_END); + if (so_size == -1) { + LOGE("Failed getting so file size: %s\n", strerror(errno)); + close(so_fd); close(memfd); return -1; } - if (sendfile(memfd, so_fd, NULL, st.st_size) == -1) { - perror("sendfile"); + if (lseek(so_fd, 0, SEEK_SET) == -1) { + LOGE("Failed seeking so file: %s\n", strerror(errno)); + + close(so_fd); + close(memfd); + + return -1; + } + + if (sendfile(memfd, so_fd, NULL, so_size) == -1) { + LOGE("Failed copying so file to memfd: %s\n", strerror(errno)); + close(so_fd); close(memfd); @@ -133,7 +145,8 @@ int create_library_fd(const char *so_path) { close(so_fd); if (fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) == -1) { - perror("fcntl"); + LOGE("Failed sealing memfd: %s\n", strerror(errno)); + close(memfd); return -1; @@ -266,14 +279,21 @@ static int spawn_companion(char *name, int lib_fd) { LOGI("Waiting for companion to start (%d)\n", pid); int status = 0; - // waitpid(pid, &status, 0); + waitpid(pid, &status, 0); LOGI("Companion exited with status %d\n", status); - // if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - if (write_string(daemon_fd, name) == -1) return -1; + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + if (write_string(daemon_fd, name) == -1) { + LOGE("Failed sending module name\n"); - if (send_fd(daemon_fd, lib_fd) == -1) return -1; + return -1; + } + if (send_fd(daemon_fd, lib_fd) == -1) { + LOGE("Failed sending lib fd\n"); + + return -1; + } LOGI("Sent module name and lib fd\n"); @@ -281,20 +301,27 @@ static int spawn_companion(char *name, int lib_fd) { ssize_t ret = read(daemon_fd, &response_buf, sizeof(response_buf)); ASSURE_SIZE_READ_WR("companion", "response", ret, sizeof(response_buf)); - uint8_t response = response_buf[0]; + LOGI("Companion response: %hhu\n", response_buf[0]); - LOGI("Companion response: %hhu\n", response); + if (response_buf[0] == 0) { + close(daemon_fd); - if (response == 0) return -2; - else if (response == 1) return daemon_fd; - else return -2; - // } else { - // LOGE("Exited with status %d\n", status); + return -1; + } else if (response_buf[0] == 1) return daemon_fd; + else { + LOGE("Invalid response from companion: %hhu\n", response_buf[0]); - // close(daemon_fd); + close(daemon_fd); - // return -1; - // } + return -1; + } + } else { + LOGE("Exited with status %d\n", status); + + close(daemon_fd); + + return -1; + } /* INFO: if pid == 0: */ } else { LOGI("Companion started (%d)\n", pid); @@ -307,11 +334,11 @@ static int spawn_companion(char *name, int lib_fd) { LOGI("Executing companion...\n"); - char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL }; - if (execv(ZYGISKD_PATH, argv) == -1) { - LOGE("Failed executing companion: %s\n", strerror(errno)); + char arg[sizeof(ZYGISKD_FILE) + sizeof(" companion ") + 32]; + snprintf(arg, sizeof(arg), "%s companion %d", ZYGISKD_FILE, companion_fd); - close(companion_fd); + if (system(arg) == -1) { + LOGE("Failed executing companion: %s\n", strerror(errno)); exit(1); } @@ -329,34 +356,60 @@ struct __attribute__((__packed__)) MsgHead { void zygiskd_start(void) { LOGI("Welcome to ReZygisk %s!", ZKSU_VERSION); + enum RootImpl impl = get_impl(); + if (impl == None) { + struct MsgHead *msg = malloc(sizeof(struct MsgHead) + sizeof("No root implementation found.")); + msg->cmd = DAEMON_SET_ERROR_INFO; + msg->length = sizeof("No root implementation found."); + memcpy(msg->data, "No root implementation found.", msg->length); + + unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead) + msg->length); + + free(msg); + } else if (impl == Multiple) { + struct MsgHead *msg = malloc(sizeof(struct MsgHead) + sizeof("Multiple root implementations found. Not supported yet.")); + msg->cmd = DAEMON_SET_ERROR_INFO; + msg->length = sizeof("Multiple root implementations found. Not supported yet."); + memcpy(msg->data, "Multiple root implementations found. Not supported yet.", msg->length); + + unix_datagram_sendto(CONTROLLER_SOCKET, &msg, sizeof(struct MsgHead) + msg->length); + + free(msg); + } + enum Architecture arch = get_arch(); struct Context context; load_modules(arch, &context); struct MsgHead *msg = NULL; - size_t msg_sz = 0; - switch (get_impl()) { - case None: { - /* INFO: Stop, compiler. */ + switch (impl) { + case None: { break; } + case Multiple: { break; } + case KernelSU: + case APatch: { + size_t root_impl_len = strlen(impl == KernelSU ? "KernelSU" : "APatch"); - break; - } - case Multiple: { - /* INFO: Stop, compiler. */ - - break; - } - - case KernelSU: { if (context.len == 0) { - msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: None") + 1; - msg = malloc(msg_sz); - + msg = malloc(sizeof(struct MsgHead) + strlen("Root: , Modules: None") + root_impl_len + 1); msg->cmd = DAEMON_SET_INFO; - msg->length = strlen("Root: KernelSU, Modules: None") + 1; - memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None")); + msg->length = strlen("Root: , Modules: None") + root_impl_len + 1; + + switch (impl) { + case None: { break; } + case Multiple: { break; } + case KernelSU: { + memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None")); + + break; + } + case APatch: { + memcpy(msg->data, "Root: APatch, Modules: None", strlen("Root: APatch, Modules: None")); + + break; + } + } } else { char *module_list = malloc(1); size_t module_list_len = 0; @@ -379,32 +432,34 @@ void zygiskd_start(void) { } } - msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: ") + module_list_len + 1; - msg = malloc(msg_sz); - + msg = malloc(sizeof(struct MsgHead) + strlen("Root: , Modules: ") + root_impl_len + module_list_len + 1); msg->cmd = DAEMON_SET_INFO; - msg->length = strlen("Root: KernelSU, Modules: ") + module_list_len + 1; - memcpy(msg->data, "Root: KernelSU, Modules: ", strlen("Root: KernelSU, Modules: ")); - memcpy(msg->data + strlen("Root: KernelSU, Modules: "), module_list, module_list_len); + msg->length = strlen("Root: , Modules: ") + root_impl_len + module_list_len + 1; + + switch (impl) { + case None: { break; } + case Multiple: { break; } + case KernelSU: { + memcpy(msg->data, "Root: KernelSU, Modules: ", strlen("Root: KernelSU, Modules: ")); + + break; + } + case APatch: { + memcpy(msg->data, "Root: APatch, Modules: ", strlen("Root: APatch, Modules: ")); + + break; + } + } + memcpy(msg->data + strlen("Root: , Modules: ") + root_impl_len, module_list, module_list_len); free(module_list); } - break; - } - default: { - msg_sz = sizeof(struct MsgHead) + strlen("Invalid root implementation") + 1; - msg = malloc(msg_sz); - - msg->cmd = DAEMON_SET_ERROR_INFO; - msg->length = strlen("Invalid root implementation") + 1; - memcpy(msg->data, "Invalid root implementation", strlen("Invalid root implementation")); - break; } } - unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, msg_sz); + unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, sizeof(struct MsgHead) + msg->length); free(msg); @@ -425,7 +480,7 @@ void zygiskd_start(void) { LOGI("Accepted client: %d\n", client_fd); - unsigned char buf[1]; + uint8_t buf[1]; ssize_t len = read(client_fd, buf, sizeof(buf)); if (len == -1) { LOGE("read: %s\n", strerror(errno)); @@ -437,7 +492,7 @@ void zygiskd_start(void) { return; } - LOGI("Action: %hhu\n", (uint8_t)buf[0]); + LOGI("Action: %hhu\n", buf[0]); enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0]; switch (action) { @@ -448,8 +503,6 @@ void zygiskd_start(void) { break; } case ZygoteRestart: { - LOGI("Zygote restart\n"); - for (int i = 0; i < context.len; i++) { if (context.modules[i].companion != -1) { close(context.modules[i].companion); @@ -465,22 +518,31 @@ void zygiskd_start(void) { break; } + /* TODO: May need to move to another thread? :/ */ case RequestLogcatFd: { - char level_buf[1]; + uint8_t level_buf[1]; ssize_t ret = read(client_fd, &level_buf, sizeof(level_buf)); ASSURE_SIZE_READ_BREAK("RequestLogcatFd", "level", ret, sizeof(level_buf)); - char level = level_buf[0]; + uint8_t level = level_buf[0]; char tag[128 + 1]; ret = read_string(client_fd, tag, sizeof(tag) - 1); - if (ret == -1) break; + if (ret == -1) { + LOGE("Failed reading tag\n"); + + break; + } tag[ret] = '\0'; char message[1024]; ret = read_string(client_fd, message, sizeof(message)); - if (ret == -1) break; + if (ret == -1) { + LOGE("Failed reading message\n"); + + break; + } __android_log_print(level, tag, "%.*s", (int)ret, message); @@ -489,13 +551,11 @@ void zygiskd_start(void) { case GetProcessFlags: { LOGI("Getting process flags\n"); - uid_t uid_buf[1]; + uint32_t uid_buf[1]; ssize_t ret = read(client_fd, &uid_buf, sizeof(uid_buf)); ASSURE_SIZE_READ_BREAK("GetProcessFlags", "uid", ret, sizeof(uid_buf)); - uid_t uid = uid_buf[0]; - - LOGI("Checking flags for uid: %d\n", uid); + uint32_t uid = uid_buf[0]; uint32_t flags = 0; if (uid_is_manager(uid)) { @@ -512,23 +572,22 @@ void zygiskd_start(void) { LOGI("Flags for uid %d: %d\n", uid, flags); switch (get_impl()) { - case None: { - break; - } - case Multiple: { - break; - } + case None: { break; } + case Multiple: { break; } case KernelSU: { flags |= PROCESS_ROOT_IS_KSU; + + break; + } + case APatch: { + flags |= PROCESS_ROOT_IS_APATCH; + + break; } } - // LOGI("Flags for uid %d: %d\n", uid, flags); - - LOGI("Sending flags\n"); - ret = write(client_fd, &flags, sizeof(flags)); - // ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags)); + ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags)); LOGI("Sent flags\n"); @@ -540,14 +599,17 @@ void zygiskd_start(void) { LOGI("Getting info\n"); switch (get_impl()) { - case None: { - break; - } - case Multiple: { - break; - } + case None: { break; } + case Multiple: { break; } case KernelSU: { flags |= PROCESS_ROOT_IS_KSU; + + break; + } + case APatch: { + flags |= PROCESS_ROOT_IS_APATCH; + + break; } } @@ -556,7 +618,7 @@ void zygiskd_start(void) { ssize_t ret = write(client_fd, &flags, sizeof(flags)); ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags)); - pid_t pid = getpid(); + uint32_t pid = getpid(); LOGI("Getting pid: %d\n", pid); @@ -565,6 +627,13 @@ void zygiskd_start(void) { LOGI("Sent pid\n"); + size_t modules_len = context.len; + ret = write(client_fd, &modules_len, sizeof(modules_len)); + + for (size_t i = 0; i < modules_len; i++) { + write_string(client_fd, context.modules[i].name); + } + break; } case ReadModules: { @@ -574,23 +643,20 @@ void zygiskd_start(void) { ssize_t ret = write(client_fd, &clen, sizeof(clen)); ASSURE_SIZE_WRITE_BREAK("ReadModules", "len", ret, sizeof(clen)); - for (int i = 0; i < (int)clen; i++) { - LOGI("Hey, we're talking about: %d\n", i); - LOGI("Writing module `%s` to stream\n", context.modules[i].name); - LOGI("Lib fd: %d\n", context.modules[i].lib_fd); + for (size_t i = 0; i < clen; i++) { + LOGI("Hey, we're talking about: %zu, with name and lib_fd: %s, %d\n", i, context.modules[i].name, context.modules[i].lib_fd); - size_t name_len = strlen(context.modules[i].name); + if (write_string(client_fd, context.modules[i].name) == -1) { + LOGE("Failed writing module name\n"); - LOGI("Name length: %zu\n", name_len); - ret = write(client_fd, &name_len, sizeof(name_len)); - ASSURE_SIZE_WRITE_BREAK("ReadModules", "name length", ret, sizeof(name_len)); + break; + } - LOGI("Writing name: %s\n", context.modules[i].name); - ret = write(client_fd, context.modules[i].name, name_len); - ASSURE_SIZE_WRITE_BREAK("ReadModules", "name", ret, name_len); + if (send_fd(client_fd, context.modules[i].lib_fd) == -1) { + LOGE("Failed sending lib fd\n"); - LOGI("Writing lib fd: %d\n", context.modules[i].lib_fd); - if (send_fd(client_fd, context.modules[i].lib_fd) == -1) break; + break; + } } LOGI("Finished reading modules to stream\n"); @@ -612,10 +678,10 @@ void zygiskd_start(void) { if (companion_fd != -1) { LOGI("Companion for module `%s` already exists\n", module->name); - if (fcntl(companion_fd, F_GETFD) == -1) { + if (!check_unix_socket(companion_fd, false)) { LOGE("Poll companion for module `%s` crashed\n", module->name); - close(companion_fd); + close(companion_fd); module->companion = -1; } } @@ -630,22 +696,26 @@ void zygiskd_start(void) { module->companion = companion_fd; - if (send_fd(client_fd, companion_fd) == -1) break; - } else if (companion_fd == -2) { - LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name); + /* INFO: Reversed params, may fix issues */ + if (send_fd(companion_fd, client_fd) == -1) { + LOGE("Failed sending companion fd\n"); - /* TODO: Avoid duplicated code -- Merge this and the one below. */ - uint8_t response = 0; - ret = write(client_fd, &response, sizeof(response)); - ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response)); + uint8_t response = 0; + ret = write(client_fd, &response, sizeof(response)); + ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response)); + } } else { - LOGE("Failed to spawn companion for `%s`\n", module->name); - - uint8_t response = 0; - ret = write(client_fd, &response, sizeof(response)); - ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response)); + if (companion_fd == -2) { + LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name); + } else { + LOGI("Could not spawn companion for `%s` due to failures.\n", module->name); + } } + uint8_t response = 0; + ret = write(client_fd, &response, sizeof(response)); + ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response)); + LOGI("Companion fd: %d\n", companion_fd); } @@ -666,19 +736,25 @@ void zygiskd_start(void) { snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name); LOGI("Module directory: %s\n", dir); + /* INFO: Maybe not read only? */ int dir_fd = open(dir, O_RDONLY); LOGI("Module directory fd: %d\n", dir_fd); - if (send_fd(client_fd, dir_fd) == -1) break; + if (send_fd(client_fd, dir_fd) == -1) { + LOGE("Failed sending module directory fd\n"); + + close(dir_fd); + + break; + } LOGI("Sent module directory fd\n"); break; } - - + /* INFO: Maybe we don't need to close? */ close(client_fd); }