From da68db8a9a9eac087724fa1a4c0b0221e6728a69 Mon Sep 17 00:00:00 2001 From: ThePedroo Date: Wed, 24 Jul 2024 13:45:57 -0300 Subject: [PATCH] add: base for C99 zygiskd This commit adds the first base for C99 zygiskd, that is not fully working or code-ready. --- zygiskd-new/.gitignore | 2 + {zygiskd => zygiskd-new}/LICENSE | 0 zygiskd-new/Makefile | 33 + zygiskd-new/companion.c | 130 ++++ zygiskd-new/companion.h | 6 + {zygiskd => zygiskd-new}/constants.h | 28 +- {zygiskd => zygiskd-new}/dl.c | 4 +- {zygiskd => zygiskd-new}/dl.h | 2 +- zygiskd-new/main.c | 93 +++ {zygiskd => zygiskd-new}/root_impl/common.c | 12 +- {zygiskd => zygiskd-new}/root_impl/common.h | 10 +- {zygiskd => zygiskd-new}/root_impl/kernelsu.c | 28 +- zygiskd-new/root_impl/kernelsu.h | 14 + zygiskd-new/utils.c | 300 ++++++++ zygiskd-new/utils.h | 36 + zygiskd-new/zygiskd.c | 722 ++++++++++++++++++ zygiskd-new/zygiskd.h | 6 + {zygiskd-old => zygiskd}/.cargo/config.toml | 0 {zygiskd-old => zygiskd}/Cargo.toml | 0 zygiskd/Makefile | 19 - {zygiskd-old => zygiskd}/build.gradle.kts | 0 zygiskd/companion.c | 96 --- zygiskd/main.c | 83 -- zygiskd/root_impl/kernelsu.h | 14 - {zygiskd-old => zygiskd}/src/companion.rs | 0 {zygiskd-old => zygiskd}/src/constants.rs | 0 {zygiskd-old => zygiskd}/src/dl.rs | 0 {zygiskd-old => zygiskd}/src/main.rs | 0 .../src/root_impl/apatch.rs | 0 .../src/root_impl/kernelsu.rs | 0 .../src/root_impl/magisk.rs | 0 {zygiskd-old => zygiskd}/src/root_impl/mod.rs | 0 {zygiskd-old => zygiskd}/src/utils.rs | 0 {zygiskd-old => zygiskd}/src/zygiskd.rs | 0 zygiskd/utils.c | 172 ----- zygiskd/utils.h | 16 - zygiskd/zygiskd | Bin 13600 -> 0 bytes zygiskd/zygiskd.c | 353 --------- 38 files changed, 1392 insertions(+), 787 deletions(-) create mode 100644 zygiskd-new/.gitignore rename {zygiskd => zygiskd-new}/LICENSE (100%) create mode 100644 zygiskd-new/Makefile create mode 100644 zygiskd-new/companion.c create mode 100644 zygiskd-new/companion.h rename {zygiskd => zygiskd-new}/constants.h (72%) rename {zygiskd => zygiskd-new}/dl.c (95%) rename {zygiskd => zygiskd-new}/dl.h (81%) create mode 100644 zygiskd-new/main.c rename {zygiskd => zygiskd-new}/root_impl/common.c (78%) rename {zygiskd => zygiskd-new}/root_impl/common.h (50%) rename {zygiskd => zygiskd-new}/root_impl/kernelsu.c (63%) create mode 100644 zygiskd-new/root_impl/kernelsu.h create mode 100644 zygiskd-new/utils.c create mode 100644 zygiskd-new/utils.h create mode 100644 zygiskd-new/zygiskd.c create mode 100644 zygiskd-new/zygiskd.h rename {zygiskd-old => zygiskd}/.cargo/config.toml (100%) rename {zygiskd-old => zygiskd}/Cargo.toml (100%) delete mode 100644 zygiskd/Makefile rename {zygiskd-old => zygiskd}/build.gradle.kts (100%) delete mode 100644 zygiskd/companion.c delete mode 100644 zygiskd/main.c delete mode 100644 zygiskd/root_impl/kernelsu.h rename {zygiskd-old => zygiskd}/src/companion.rs (100%) rename {zygiskd-old => zygiskd}/src/constants.rs (100%) rename {zygiskd-old => zygiskd}/src/dl.rs (100%) rename {zygiskd-old => zygiskd}/src/main.rs (100%) rename {zygiskd-old => zygiskd}/src/root_impl/apatch.rs (100%) rename {zygiskd-old => zygiskd}/src/root_impl/kernelsu.rs (100%) rename {zygiskd-old => zygiskd}/src/root_impl/magisk.rs (100%) rename {zygiskd-old => zygiskd}/src/root_impl/mod.rs (100%) rename {zygiskd-old => zygiskd}/src/utils.rs (100%) rename {zygiskd-old => zygiskd}/src/zygiskd.rs (100%) delete mode 100644 zygiskd/utils.c delete mode 100644 zygiskd/utils.h delete mode 100755 zygiskd/zygiskd delete mode 100644 zygiskd/zygiskd.c diff --git a/zygiskd-new/.gitignore b/zygiskd-new/.gitignore new file mode 100644 index 0000000..8f961c3 --- /dev/null +++ b/zygiskd-new/.gitignore @@ -0,0 +1,2 @@ +zygiskd64 +zygiskd32 \ No newline at end of file diff --git a/zygiskd/LICENSE b/zygiskd-new/LICENSE similarity index 100% rename from zygiskd/LICENSE rename to zygiskd-new/LICENSE diff --git a/zygiskd-new/Makefile b/zygiskd-new/Makefile new file mode 100644 index 0000000..da67f95 --- /dev/null +++ b/zygiskd-new/Makefile @@ -0,0 +1,33 @@ +CC := ~/Android/Sdk/ndk/27.0.11902837/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android34-clang + +# FILES = root_impl/common.c \ +# root_impl/kernelsu.c \ +# companion.c \ +# dl.c \ +# main.c \ +# utils.c \ +# zygiskd.c + +FILES = root_impl/*.c \ + *.c + +CFLAGS = -D_GNU_SOURCE -std=c99 -Wpedantic -Wall -Wextra -Werror -Wformat -Wuninitialized -Wshadow -Wno-zero-length-array -Wno-fixed-enum-extension -Iroot_impl -llog + +all: CFLAGS += -DDEBUG=0 -O3 -flto=thin -Wl,--strip-all +all: + $(CC) $(CFLAGS) $(FILES) -o zygiskd64 + +debug: CFLAGS += -DDEBUG=1 -g -O0 +debug: + $(CC) $(CFLAGS) $(FILES) -o zygiskd64 + +32bit: CFLAGS += -m32 -DDEBUG=0 -O3 -flto=thin -Wl,--strip-all +32bit: + $(CC) $(CFLAGS) $(FILES) -o zygiskd32 + +32bit-debug: CFLAGS += -m32 -DDEBUG=1 -g -O0 +32bit-debug: + $(CC) $(CFLAGS) $(FILES) -o zygiskd32 + +clean: + rm -f zygiskd \ No newline at end of file diff --git a/zygiskd-new/companion.c b/zygiskd-new/companion.c new file mode 100644 index 0000000..f7c7547 --- /dev/null +++ b/zygiskd-new/companion.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "companion.h" +#include "dl.h" +#include "utils.h" + +typedef void (*ZygiskCompanionEntryFn)(int); + +ZygiskCompanionEntryFn load_module(int fd) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + + void *handle = android_dlopen(path, RTLD_NOW); + void *entry = dlsym(handle, "zygisk_companion_entry"); + if (entry == NULL) return NULL; + + return (ZygiskCompanionEntryFn)entry; +} + +void *ExecuteNew(void *arg) { + int fd = *((int *)arg); + + struct stat st0; + if (fstat(fd, &st0) == -1) { + LOGE("Failed to stat client fd\n"); + + free(arg); + + exit(0); + } + entry(fd); + + // Only close client if it is the same file so we don't + // accidentally close a re-used file descriptor. + // This check is required because the module companion + // handler could've closed the file descriptor already. + struct stat st1; + if (fstat(fd, &st1) == -1) { + LOGE("Failed to stat client fd\n"); + + free(arg); + + exit(0); + } + + if (st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino) { + close(fd); + } + + free(arg); + + return NULL; +} + + +void entry(int fd) { + LOGI("Previous error (2): %s\n", strerror(errno)); + + LOGI("companion entry fd: |%d|\n", fd); + + LOGI("Reading name length\n"); + + char name[256 + 1]; + LOGI("Previous error(6): %s\n", strerror(errno)); + + /* INFO: Getting stuck here */ + ssize_t ret = read_string(fd, name, sizeof(name) - 1); + if (ret == -1) return; + + name[ret] = '\0'; + + LOGI("Companion process requested for `%s`\n", name); + + // int library_fd; + // recv_fd(fd, &library_fd); + + // LOGI("Library fd: %d\n", library_fd); + + // ZygiskCompanionEntryFn entry = load_module(library_fd); + + // LOGI("Library loaded\n"); + + // close(library_fd); + + // LOGI("Library closed\n"); + + // if (entry == NULL) { + // LOGI("No companion entry for: %s\n", name); + + // write(fd, (void *)0, 1); + + // return; + // } + + // LOGI("Companion process created for: %s\n", name); + + // write(fd, (void *)1, 1); + + // while (1) { + // int client_fd; + // recv_fd(fd, &client_fd); + + // LOGI("New companion request from module \"%s\" with fd \"%d\"\n", name, client_fd); + + // int response = 1; + // write(fd, (void *)&response, sizeof(response)); + + // 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_detach(thread); + // } +} diff --git a/zygiskd-new/companion.h b/zygiskd-new/companion.h new file mode 100644 index 0000000..1b931e8 --- /dev/null +++ b/zygiskd-new/companion.h @@ -0,0 +1,6 @@ +#ifndef COMPANION_H +#define COMPANION_H + +void entry(int fd); + +#endif /* COMPANION_H */ diff --git a/zygiskd/constants.h b/zygiskd-new/constants.h similarity index 72% rename from zygiskd/constants.h rename to zygiskd-new/constants.h index a3c7cf4..94a7f5a 100644 --- a/zygiskd/constants.h +++ b/zygiskd-new/constants.h @@ -28,15 +28,14 @@ #endif #if (defined(__LP64__) || defined(_LP64)) - #define lp_select(a, b) a -#else #define lp_select(a, b) b +#else + #define lp_select(a, b) a #endif -#define PATH_MODULES_DIR ".." -#define ZYGOTE_INJECTED (lp_select(5, 4)) -#define DAEMON_SET_INFO (lp_select(7, 6)) -#define DAEMON_SET_ERROR_INFO (lp_select(9, 8)) +#define ZYGOTE_INJECTED lp_select(5, 4) +#define DAEMON_SET_INFO lp_select(7, 6) +#define DAEMON_SET_ERROR_INFO lp_select(9, 8) #define SYSTEM_SERVER_STARTED 10 enum DaemonSocketAction { @@ -51,14 +50,15 @@ enum DaemonSocketAction { SystemServerStarted }; -enum ProcessFlags { - PROCESS_GRANTED_ROOT = 1 << 0, - PROCESS_ON_DENYLIST = 1 << 1, - PROCESS_IS_MANAGER = 1 << 28, - PROCESS_ROOT_IS_APATCH = 1 << 27, - PROCESS_ROOT_IS_KSU = 1 << 29, - PROCESS_ROOT_IS_MAGISK = 1 << 30, - PROCESS_IS_SYSUI = 1 << 31 +enum ProcessFlags: uint32_t { + PROCESS_GRANTED_ROOT = (1u << 0), + PROCESS_ON_DENYLIST = (1u << 1), + PROCESS_IS_MANAGER = (1u << 28), + PROCESS_ROOT_IS_APATCH = (1u << 27), + PROCESS_ROOT_IS_KSU = (1u << 29), + PROCESS_ROOT_IS_MAGISK = (1u << 30), + PROCESS_IS_SYS_UI = (1u << 31), + PROCESS_IS_SYSUI = (1u << 31) }; enum RootImplState { diff --git a/zygiskd/dl.c b/zygiskd-new/dl.c similarity index 95% rename from zygiskd/dl.c rename to zygiskd-new/dl.c index 36582b6..eddcf1f 100644 --- a/zygiskd/dl.c +++ b/zygiskd-new/dl.c @@ -17,7 +17,7 @@ struct AndroidDlextinfo { size_t reserved_size; int relro_fd; int library_fd; - __off64_t library_fd_offset; + off64_t library_fd_offset; struct AndroidNamespace *library_namespace; }; @@ -45,7 +45,7 @@ void *android_dlopen(char *path, u_int32_t flags) { ANDROID_NAMESPACE_TYPE_SHARED, NULL, NULL, - &android_dlopen + (void *)&android_dlopen ); if (ns != NULL) { diff --git a/zygiskd/dl.h b/zygiskd-new/dl.h similarity index 81% rename from zygiskd/dl.h rename to zygiskd-new/dl.h index acdf231..32cd248 100644 --- a/zygiskd/dl.h +++ b/zygiskd-new/dl.h @@ -3,4 +3,4 @@ void *android_dlopen(char *path, u_int32_t flags); -#endif /* DL_H */ \ No newline at end of file +#endif /* DL_H */ diff --git a/zygiskd-new/main.c b/zygiskd-new/main.c new file mode 100644 index 0000000..2ad217d --- /dev/null +++ b/zygiskd-new/main.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#include + +#include "root_impl/common.h" +#include "companion.h" +#include "zygiskd.h" + +#include "utils.h" + +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]); + } + + if (argc > 1) { + if (strcmp(argv[1], "companion") == 0) { + if (argc < 3) { + LOGI("Usage: zygiskd companion \n"); + + return 1; + } + + LOGI("Previous error{3}: %s\n", strerror(errno)); + + int fd = atoi(argv[2]); + LOGI("Previous error(4): %s\n", strerror(errno)); + + entry(fd); + + return 0; + } + + else if (strcmp(argv[1], "version") == 0) { + LOGI("ReZygisk Daemon %s\n", ZKSU_VERSION); + + return 0; + } + + else if (strcmp(argv[1], "root") == 0) { + root_impls_setup(); + enum RootImpl impl = get_impl(); + + switch (impl) { + case None: { + LOGI("No root implementation found.\n"); + + return 1; + } + + case Multiple: { + LOGI("Multiple root implementations found.\n"); + + return 1; + } + + case KernelSU: { + LOGI("KernelSU root implementation found.\n"); + + return 0; + } + } + + + return 0; + } + + else { + LOGI("Usage: zygiskd [companion|version|root]\n"); + + return 0; + } + } + + LOGI("Previous error{27}: %s\n", strerror(errno)); + switch_mount_namespace((pid_t)1); + LOGI("Previous error{28}: %s\n", strerror(errno)); + root_impls_setup(); + LOGI("Previous error{29}: %s\n", strerror(errno)); + zygiskd_start(); + + return 0; +} diff --git a/zygiskd/root_impl/common.c b/zygiskd-new/root_impl/common.c similarity index 78% rename from zygiskd/root_impl/common.c rename to zygiskd-new/root_impl/common.c index 684ca89..ddc75c1 100644 --- a/zygiskd/root_impl/common.c +++ b/zygiskd-new/root_impl/common.c @@ -1,10 +1,12 @@ +#include + #include "kernelsu.h" #include "common.h" static enum RootImpl ROOT_IMPL = None; -void root_impls_setup() { +void root_impls_setup(void) { enum RootImplState ksu_version = ksu_get_kernel_su(); enum RootImpl impl = None; @@ -14,11 +16,11 @@ void root_impls_setup() { ROOT_IMPL = impl; } -enum RootImpl get_impl() { +enum RootImpl get_impl(void) { return ROOT_IMPL; } -bool uid_granted_root(int uid) { +bool uid_granted_root(uid_t uid) { switch (get_impl()) { case KernelSU: { return ksu_uid_granted_root(uid); @@ -29,7 +31,7 @@ bool uid_granted_root(int uid) { } } -bool uid_should_umount(int uid) { +bool uid_should_umount(uid_t uid) { switch (get_impl()) { case KernelSU: { return ksu_uid_should_umount(uid); @@ -40,7 +42,7 @@ bool uid_should_umount(int uid) { } } -bool uid_is_manager(int uid) { +bool uid_is_manager(uid_t uid) { switch (get_impl()) { case KernelSU: { return ksu_uid_is_manager(uid); diff --git a/zygiskd/root_impl/common.h b/zygiskd-new/root_impl/common.h similarity index 50% rename from zygiskd/root_impl/common.h rename to zygiskd-new/root_impl/common.h index d1a088a..314caf3 100644 --- a/zygiskd/root_impl/common.h +++ b/zygiskd-new/root_impl/common.h @@ -9,14 +9,14 @@ enum RootImpl { KernelSU }; -void root_impls_setup(); +void root_impls_setup(void); -enum RootImpl get_impl(); +enum RootImpl get_impl(void); -bool uid_granted_root(int uid); +bool uid_granted_root(uid_t uid); -bool uid_should_umount(int uid); +bool uid_should_umount(uid_t uid); -bool uid_is_manager(int uid); +bool uid_is_manager(uid_t uid); #endif /* COMMON_H */ diff --git a/zygiskd/root_impl/kernelsu.c b/zygiskd-new/root_impl/kernelsu.c similarity index 63% rename from zygiskd/root_impl/kernelsu.c rename to zygiskd-new/root_impl/kernelsu.c index cfa28e3..b8f950c 100644 --- a/zygiskd/root_impl/kernelsu.c +++ b/zygiskd-new/root_impl/kernelsu.c @@ -1,9 +1,10 @@ #include - #include #include +#include #include "../constants.h" +#include "../utils.h" #include "kernelsu.h" @@ -13,11 +14,13 @@ #define CMD_UID_GRANTED_ROOT 12 #define CMD_UID_SHOULD_UMOUNT 13 -enum RootImplState ksu_get_kernel_su() { +enum RootImplState ksu_get_kernel_su(void) { int version = 0; prctl(KERNEL_SU_OPTION, CMD_GET_VERSION, &version, 0, 0); - if (version == 0) return -1; + errno = 0; + + if (version == 0) return Abnormal; if (version >= MIN_KSU_VERSION && version <= MAX_KSU_VERSION) return Supported; @@ -26,29 +29,40 @@ enum RootImplState ksu_get_kernel_su() { return Abnormal; } -bool ksu_uid_granted_root(int uid) { +bool ksu_uid_granted_root(uid_t uid) { uint32_t result = 0; 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; } -bool ksu_uid_should_umount(int uid) { +bool ksu_uid_should_umount(uid_t uid) { uint32_t result = 0; 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(int uid) { +bool ksu_uid_is_manager(uid_t uid) { + struct stat s; - if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == 0) return s.st_uid == (uid_t)uid; + if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == 0) { + LOGI("ksu_uid_is_manager: %d", uid); + + return s.st_uid == uid; + } + + LOGI("ksu_uid_is_manager: false"); return false; } diff --git a/zygiskd-new/root_impl/kernelsu.h b/zygiskd-new/root_impl/kernelsu.h new file mode 100644 index 0000000..1f2c494 --- /dev/null +++ b/zygiskd-new/root_impl/kernelsu.h @@ -0,0 +1,14 @@ +#ifndef KERNELSU_H +#define KERNELSU_H + +#include "../constants.h" + +enum RootImplState ksu_get_kernel_su(void); + +bool ksu_uid_granted_root(uid_t uid); + +bool ksu_uid_should_umount(uid_t uid); + +bool ksu_uid_is_manager(uid_t uid); + +#endif diff --git a/zygiskd-new/utils.c b/zygiskd-new/utils.c new file mode 100644 index 0000000..9a6d01b --- /dev/null +++ b/zygiskd-new/utils.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "utils.h" + +void switch_mount_namespace(pid_t pid) { + char current_path[PATH_MAX]; + if (getcwd(current_path, PATH_MAX) == NULL) { + /* TODO: Improve error messages */ + LOGE("getcwd: %s\n", strerror(errno)); + + return; + } + + /* INFO: We will NEVER achieve PATH_MAX value, but this is for ensurance. */ + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "/proc/%d/ns/mnt", pid); + + FILE *mnt_ns = fopen(path, "r"); + if (mnt_ns == NULL) { + /* TODO: Improve error messages */ + LOGE("fopen: %s\n", strerror(errno)); + + return; + } + + if (setns(fileno(mnt_ns), 0) == -1) { + /* TODO: Improve error messages */ + LOGE("setns: %s\n", strerror(errno)); + + return; + } + + fclose(mnt_ns); + + if (chdir(current_path) == -1) { + /* TODO: Improve error messages */ + LOGE("chdir: %s\n", strerror(errno)); + + return; + } +} + +int __system_property_get(const char *, char *); + +void get_property(const char *name, char *output) { + __system_property_get(name, output); +} + +void set_socket_create_context(const char *context) { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "/proc/thread-self/attr/sockcreate"); + + FILE *sockcreate = fopen(path, "w"); + if (sockcreate == NULL) { + LOGE("fopen: %s\n", strerror(errno)); + + return; + } + + if (fwrite(context, 1, strlen(context), sockcreate) != strlen(context)) { + LOGE("fwrite: %s\n", strerror(errno)); + + return; + } + + fclose(sockcreate); +} + +static void get_current_attr(char *output) { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "/proc/self/attr/current"); + + FILE *current = fopen(path, "r"); + if (current == NULL) { + LOGE("fopen: %s\n", strerror(errno)); + + return; + } + + if (fgets(output, PATH_MAX, current) == NULL) { + LOGE("fgets: %s\n", strerror(errno)); + + return; + } + + fclose(current); +} + +void unix_datagram_sendto(const char *path, void *buf, size_t len) { + char current_attr[PATH_MAX]; + get_current_attr(current_attr); + + set_socket_create_context(current_attr); + + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + + strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); + + int socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (socket_fd == -1) { + LOGE("socket: %s\n", strerror(errno)); + + return; + } + + if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + LOGE("connect: %s\n", strerror(errno)); + + return; + } + + if (sendto(socket_fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + LOGE("sendto: %s\n", strerror(errno)); + + return; + } + + set_socket_create_context("u:r:zygote:s0"); + + close(socket_fd); +} + +int chcon(const char *path, const char *context) { + char command[PATH_MAX]; + snprintf(command, PATH_MAX, "chcon %s %s", context, path); + + return system(command); +} + +int unix_listener_from_path(char *path) { + if (remove(path) == -1 && errno != ENOENT) { + LOGE("remove: %s\n", strerror(errno)); + + return -1; + } + + int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (socket_fd == -1) { + LOGE("socket: %s\n", strerror(errno)); + + return -1; + } + + struct sockaddr_un addr; + + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); + + if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { + LOGE("bind: %s\n", strerror(errno)); + + return -1; + } + + if (listen(socket_fd, 2) == -1) { + LOGE("listen: %s\n", strerror(errno)); + + return -1; + } + + if (chcon(path, "u:object_r:magisk_file:s0") == -1) { + LOGE("chcon: %s\n", strerror(errno)); + + return -1; + } + + return socket_fd; +} + +ssize_t send_fd(int sockfd, int fd) { + char control_buf[CMSG_SPACE(sizeof(int))]; + memset(control_buf, 0, sizeof(control_buf)); + + int cnt = 1; + struct iovec iov = { + .iov_base = &cnt, + .iov_len = sizeof(cnt) + }; + + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = control_buf, + .msg_controllen = sizeof(control_buf) + }; + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + + memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + ssize_t sent_bytes = sendmsg(sockfd, &msg, 0); + if (sent_bytes == -1) { + LOGE("Failed to send fd: %s\n", strerror(errno)); + + return -1; + } + + return sent_bytes; +} + +ssize_t recv_fd(int sockfd, int *fd) { + char control_buf[CMSG_SPACE(sizeof(int))]; + memset(control_buf, 0, sizeof(control_buf)); + + int cnt = 1; + struct iovec iov = { + .iov_base = &cnt, + .iov_len = sizeof(cnt) + }; + + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = control_buf, + .msg_controllen = sizeof(control_buf) + }; + + ssize_t received_bytes = recvmsg(sockfd, &msg, 0); + if (received_bytes == -1) { + LOGE("Failed to read fd: %s\n", strerror(errno)); + + return -1; + } + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + memcpy(fd, CMSG_DATA(cmsg), sizeof(int)); + + return received_bytes; +} + +ssize_t write_string(int fd, const char *str) { + size_t len = strlen(str); + + ssize_t written_bytes = write(fd, &len, sizeof(len)); + if (written_bytes != sizeof(len)) { + LOGE("Failed to write string length: %s\n", strerror(errno)); + + return -1; + } + + written_bytes = write(fd, str, len); + if ((size_t)written_bytes != len) { + LOGE("Failed to write string: Not all bytes were written.\n"); + + return -1; + } + + return written_bytes; +} + +ssize_t read_string(int fd, char *str, size_t len) { + size_t str_len_buf[1]; + + LOGI("Reading string length from fd %d\n", fd); + LOGI("Previous error: %s\n", strerror(errno)); + + ssize_t read_bytes = read(fd, &str_len_buf, sizeof(str_len_buf)); + + LOGI("Read %zd bytes\n", read_bytes); + if (read_bytes != (ssize_t)sizeof(str_len_buf)) { + LOGE("Failed to read string length: %s\n", strerror(errno)); + + return -1; + } + + size_t str_len = str_len_buf[0]; + + if (str_len > len) { + LOGE("Failed to read string: Buffer is too small (%zu > %zu).\n", str_len, len); + + return -1; + } + + read_bytes = read(fd, str, str_len); + if (read_bytes != (ssize_t)str_len) { + LOGE("Failed to read string: Not all bytes were read (%zd != %zu).\n", read_bytes, str_len); + + return -1; + } + + return read_bytes; +} diff --git a/zygiskd-new/utils.h b/zygiskd-new/utils.h new file mode 100644 index 0000000..b86c869 --- /dev/null +++ b/zygiskd-new/utils.h @@ -0,0 +1,36 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +#include "constants.h" + +#define LOGI(...) \ + __android_log_print(ANDROID_LOG_INFO, lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \ + printf(__VA_ARGS__) + +#define LOGE(...) \ + __android_log_print(ANDROID_LOG_INFO , lp_select("zygiskd32", "zygiskd64"), __VA_ARGS__); \ + printf(__VA_ARGS__) + +void switch_mount_namespace(pid_t pid); + +void get_property(const char *name, char *output); + +void set_socket_create_context(const char *context); + +void unix_datagram_sendto(const char *path, void *buf, size_t len); + +int chcon(const char *path, const char *context); + +int unix_listener_from_path(char *path); + +ssize_t send_fd(int sockfd, int fd); + +ssize_t recv_fd(int sockfd, int *fd); + +ssize_t write_string(int fd, const char *str); + +ssize_t read_string(int fd, char *str, size_t len); + +#endif /* UTILS_H */ diff --git a/zygiskd-new/zygiskd.c b/zygiskd-new/zygiskd.c new file mode 100644 index 0000000..85036c6 --- /dev/null +++ b/zygiskd-new/zygiskd.c @@ -0,0 +1,722 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "root_impl/common.h" +#include "constants.h" +#include "utils.h" + +struct Module { + char *name; + int lib_fd; + int companion; +}; + +struct Context { + struct Module *modules; + int len; +}; + +enum Architecture { + ARM32, + ARM64, + X86, + X86_64, +}; + +#define PATH_MODULES_DIR "/data/adb/modules" +#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_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64") + +#define ASSURE_SIZE_WRITE(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + return; \ + } + +#define ASSURE_SIZE_READ(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + return; \ + } + +#define ASSURE_SIZE_WRITE_BREAK(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + break; \ + } + +#define ASSURE_SIZE_READ_BREAK(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + break; \ + } + +#define ASSURE_SIZE_WRITE_WR(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to sent " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + return -1; \ + } + +#define ASSURE_SIZE_READ_WR(area_name, subarea_name, sent_size, expected_size) \ + if (sent_size != (ssize_t)(expected_size)) { \ + LOGE("Failed to read " subarea_name " in " area_name ": Expected %zu, got %zd\n", expected_size, sent_size); \ + \ + return -1; \ + } + +static enum Architecture get_arch(void) { + char system_arch[32]; + get_property("ro.product.cpu.abi", 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); + + LOGE("Unsupported system architecture: %s\n", system_arch); + exit(1); +} + +int create_library_fd(const char *so_path) { + int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING); + if (memfd == -1) { + perror("memfd_create"); + + return -1; + } + + int so_fd = open(so_path, O_RDONLY); + if (so_fd == -1) { + perror("open"); + close(memfd); + + return -1; + } + + struct stat st; + if (fstat(so_fd, &st) == -1) { + perror("fstat"); + close(so_fd); + close(memfd); + + return -1; + } + + if (sendfile(memfd, so_fd, NULL, st.st_size) == -1) { + perror("sendfile"); + close(so_fd); + close(memfd); + + return -1; + } + + close(so_fd); + + if (fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) == -1) { + perror("fcntl"); + close(memfd); + + return -1; + } + + return memfd; +} + + +/* WARNING: Dynamic memory based */ +static void load_modules(enum Architecture arch, struct Context *context) { + context->len = 0; + context->modules = malloc(1); + + // LOGI("Previous error{25}: %s\n", strerror(errno)); + + DIR *dir = opendir(PATH_MODULES_DIR); + if (dir == NULL) { + LOGE("Failed opening modules directory: %s.", PATH_MODULES_DIR); + + return; + } + + // LOGI("Previous error{27}: %s\n", strerror(errno)); + + char arch_str[32]; + switch (arch) { + case ARM32: { + strcpy(arch_str, "armeabi-v7a"); + + break; + } + case ARM64: { + strcpy(arch_str, "arm64-v8a"); + + break; + } + case X86: { + strcpy(arch_str, "x86"); + + break; + } + case X86_64: { + strcpy(arch_str, "x86_64"); + + break; + } + } + + LOGI("Loading modules for architecture: %s\n", arch_str); + // LOGI("Previous error{28}: %s\n", strerror(errno)); + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + // LOGI("Previous error{29}: %s\n", strerror(errno)); + if (entry->d_type != DT_DIR) continue; /* INFO: Only directories */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, "zygisksu") == 0) continue; + + char *name = entry->d_name; + char so_path[PATH_MAX]; + snprintf(so_path, PATH_MAX, "/data/adb/modules/%s/zygisk/%s.so", name, arch_str); + + struct stat st; + if (stat(so_path, &st) == -1) { + errno = 0; + + continue; + } + + char disabled[PATH_MAX]; + snprintf(disabled, PATH_MAX, "/data/adb/modules/%s/disable", name); + + if (stat(disabled, &st) != -1) { + errno = 0; + + continue; + } + + LOGI("Loading module `%s`...\n", name); + int lib_fd = create_library_fd(so_path); + if (lib_fd == -1) { + LOGE("Failed loading module `%s`\n", name); + + continue; + } + + LOGI("Loaded module lib fd: %d\n", lib_fd); + + context->modules = realloc(context->modules, ((context->len + 1) * sizeof(struct Module))); + context->modules[context->len].name = strdup(name); + context->modules[context->len].lib_fd = lib_fd; + context->modules[context->len].companion = -1; + context->len++; + } +} + +static void free_modules(struct Context *context) { + for (int i = 0; i < context->len; i++) { + free(context->modules[i].name); + if (context->modules[i].companion != -1) close(context->modules[i].companion); + } +} + +static int create_daemon_socket(void) { + set_socket_create_context("u:r:zygote:s0"); + + return unix_listener_from_path(PATH_CP_NAME); +} + +static int spawn_companion(char *name, int lib_fd) { + // LOGI("Previous error{15}: %s\n", strerror(errno)); + + int sockets[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { + LOGE("Failed creating socket pair.\n"); + + return -1; + } + + int daemon_fd = sockets[0]; + int companion_fd = sockets[1]; + + LOGI("Companion fd: %d\n", companion_fd); + LOGI("Daemon fd: %d\n", daemon_fd); + + // LOGI("Previous error{13}: %s\n", strerror(errno)); + + pid_t pid = fork(); + LOGI("Forked: %d\n", pid); + if (pid < 0) { + LOGE("Failed forking companion: %s\n", strerror(errno)); + + close(companion_fd); + close(daemon_fd); + + exit(1); + } else if (pid > 0) { + // LOGI("Previous error{11}: %s\n", strerror(errno)); + + close(companion_fd); + + LOGI("Waiting for companion to start (%d)\n", pid); + // LOGI("Previous error{8}: %s\n", strerror(errno)); + + int status; + waitpid(pid, &status, 0); + + LOGI("Companion exited with status %d\n", status); + // LOGI("Previous error{9}: %s\n", strerror(errno)); + + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + if (write_string(daemon_fd, name) == -1) return -1; + + if (send_fd(daemon_fd, lib_fd) == -1) return -1; + + LOGI("Sent module name and lib fd\n"); + + uint8_t response_buf[1]; + ssize_t ret = read(daemon_fd, &response_buf, sizeof(response_buf)); + ASSURE_SIZE_READ_WR("companion", "response", ret, sizeof(response_buf)); + + uint8_t response = response_buf[0]; + + LOGI("Companion response: %hhu\n", response); + + if (response == 0) return -2; + else if (response == 1) return daemon_fd; + else return -2; + } else { + LOGE("Exited with status %d\n", status); + + close(daemon_fd); + + return -1; + } + /* INFO: if pid == 0: */ + } else { + LOGI("Companion started (%d)\n", pid); + /* INFO: There is no case where this will fail with a valid fd. */ + fcntl(companion_fd, F_SETFD, 0); + } + + char companion_fd_str[32]; + snprintf(companion_fd_str, 32, "%d", companion_fd); + + LOGI("Executing companion...\n"); + // LOGI("Previous error{10}: %s\n", strerror(errno)); + + char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL }; + if (execv(ZYGISKD_PATH, argv) == -1) { + LOGE("Failed executing companion: %s\n", strerror(errno)); + + close(companion_fd); + + exit(1); + } + + exit(0); +} + +/* TODO: Is packed attribute really necessary? */ +struct __attribute__((__packed__)) MsgHead { + unsigned int cmd; + int length; + char data[0]; +}; + +void zygiskd_start(void) { + LOGI("Welcome to ReZygisk %s!", ZKSU_VERSION); + + // LOGI("Previous error{26}: %s\n", strerror(errno)); + + enum Architecture arch = get_arch(); + + // LOGI("Previous error{25}: %s\n", strerror(errno)); + + struct Context context; + load_modules(arch, &context); + + struct MsgHead *msg = NULL; + size_t msg_sz = 0; + + // LOGI("Previous error{24}: %s\n", strerror(errno)); + + switch (get_impl()) { + case None: { + /* INFO: Stop, compiler. */ + + 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->cmd = DAEMON_SET_INFO; + msg->length = strlen("Root: KernelSU, Modules: None") + 1; + memcpy(msg->data, "Root: KernelSU, Modules: None", strlen("Root: KernelSU, Modules: None")); + } else { + char *module_list = malloc(1); + size_t module_list_len = 0; + + for (int i = 0; i < context.len; i++) { + if (i != context.len - 1) { + module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + strlen(", ") + 1); + memcpy(module_list + module_list_len, context.modules[i].name, strlen(context.modules[i].name)); + + module_list_len += strlen(context.modules[i].name); + + memcpy(module_list + module_list_len, ", ", strlen(", ")); + + module_list_len += strlen(", "); + } else { + module_list = realloc(module_list, module_list_len + strlen(context.modules[i].name) + 1); + memcpy(module_list + module_list_len, context.modules[i].name, strlen(context.modules[i].name)); + + module_list_len += strlen(context.modules[i].name); + } + } + + msg_sz = sizeof(struct MsgHead) + strlen("Root: KernelSU, Modules: ") + module_list_len + 1; + msg = malloc(msg_sz); + + 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); + + 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; + } + } + + // LOGI("Previous error{22}: %s\n", strerror(errno)); + + unix_datagram_sendto(CONTROLLER_SOCKET, (void *)msg, msg_sz); + + free(msg); + + // LOGI("Previous error{21}: %s\n", strerror(errno)); + + int socket_fd = create_daemon_socket(); + if (socket_fd == -1) { + LOGE("Failed creating daemon socket\n"); + + return; + } + + while (1) { + // LOGI("Previous error{20}: %s\n", strerror(errno)); + int client_fd = accept(socket_fd, NULL, NULL); + if (client_fd == -1) { + LOGE("accept: %s\n", strerror(errno)); + + return; + } + + LOGI("Accepted client: %d\n", client_fd); + + // LOGI("Previous error{19}: %s\n", strerror(errno)); + + unsigned char buf[1]; + ssize_t len = read(client_fd, buf, sizeof(buf)); + if (len == -1) { + LOGE("read: %s\n", strerror(errno)); + + return; + } else if (len == 0) { + LOGI("Client disconnected\n"); + + return; + } + + LOGI("Action: %hhu\n", (uint8_t)buf[0]); + enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0]; + + switch (action) { + case PingHeartbeat: { + enum DaemonSocketAction msgr = ZYGOTE_INJECTED; + unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + + 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); + context.modules[i].companion = -1; + } + } + + break; + } + case SystemServerStarted: { + enum DaemonSocketAction msgr = SYSTEM_SERVER_STARTED; + unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + + break; + } + case RequestLogcatFd: { + char 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]; + + char tag[128 + 1]; + ret = read_string(client_fd, tag, sizeof(tag) - 1); + if (ret == -1) break; + + tag[ret] = '\0'; + + char message[1024]; + ret = read_string(client_fd, message, sizeof(message)); + if (ret == -1) break; + + __android_log_print(level, tag, "%.*s", (int)ret, message); + + break; + } + case GetProcessFlags: { + LOGI("Getting process flags\n"); + + uid_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 flags = 0; + if (uid_is_manager(uid)) { + flags |= PROCESS_IS_MANAGER; + } else { + if (uid_granted_root(uid)) { + flags |= PROCESS_GRANTED_ROOT; + } + if (uid_should_umount(uid)) { + flags |= PROCESS_ON_DENYLIST; + } + } + + LOGI("Flags for uid %d: %d\n", uid, flags); + + switch (get_impl()) { + case None: { + break; + } + case Multiple: { + break; + } + case KernelSU: { + flags |= PROCESS_ROOT_IS_KSU; + } + } + + // 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)); + + LOGI("Sent flags\n"); + + break; + } + case GetInfo: { + uint32_t flags = 0; + + LOGI("Getting info\n"); + + switch (get_impl()) { + case None: { + break; + } + case Multiple: { + break; + } + case KernelSU: { + flags |= PROCESS_ROOT_IS_KSU; + } + } + + LOGI("Flags: %d\n", flags); + + ssize_t ret = write(client_fd, &flags, sizeof(flags)); + ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags)); + + pid_t pid = getpid(); + + LOGI("Getting pid: %d\n", pid); + + ret = write(client_fd, &pid, sizeof(pid)); + ASSURE_SIZE_WRITE_BREAK("GetInfo", "pid", ret, sizeof(pid)); + + LOGI("Sent pid\n"); + + break; + } + case ReadModules: { + LOGI("Reading modules to stream\n"); + + size_t clen = context.len; + 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); + + size_t name_len = strlen(context.modules[i].name); + + 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)); + + 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); + + LOGI("Writing lib fd: %d\n", context.modules[i].lib_fd); + if (send_fd(client_fd, context.modules[i].lib_fd) == -1) break; + } + + LOGI("Finished reading modules to stream\n"); + + break; + } + case RequestCompanionSocket: { + LOGI("Requesting companion socket\n"); + + // LOGI("Previous error{17}: %s\n", strerror(errno)); + + size_t index_buf[1]; + ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf)); + ASSURE_SIZE_READ_BREAK("RequestCompanionSocket", "index", ret, sizeof(index_buf)); + + // LOGI("Previous error{16}: %s\n", strerror(errno)); + + size_t index = index_buf[0]; + + struct Module *module = &context.modules[index]; + int companion_fd = module->companion; + + if (companion_fd != -1) { + LOGI("Companion for module `%s` already exists\n", module->name); + + if (fcntl(companion_fd, F_GETFD) == -1) { + LOGE("Poll companion for module `%s` crashed\n", module->name); + close(companion_fd); + + module->companion = -1; + } + } + + if (companion_fd == -1) { + LOGI("Spawning companion for `%s`\n", module->name); + + companion_fd = spawn_companion(module->name, module->lib_fd); + + if (companion_fd != -1) { + LOGI("Spawned companion for `%s`\n", module->name); + + 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); + + /* 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)); + } 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)); + } + + LOGI("Companion fd: %d\n", companion_fd); + } + + break; + } + case GetModuleDir: { + LOGI("Getting module directory\n"); + + size_t index_buf[1]; + ssize_t ret = read(client_fd, &index_buf, sizeof(index_buf)); + ASSURE_SIZE_READ_BREAK("GetModuleDir", "index", ret, sizeof(index_buf)); + + size_t index = index_buf[0]; + + LOGI("Index: %zu\n", index); + + char dir[PATH_MAX]; + snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name); + + LOGI("Module directory: %s\n", dir); + int dir_fd = open(dir, O_RDONLY); + + LOGI("Module directory fd: %d\n", dir_fd); + + if (send_fd(client_fd, dir_fd) == -1) break; + + LOGI("Sent module directory fd\n"); + + break; + } + + + + close(client_fd); + } + + continue; + } + + close(socket_fd); + free_modules(&context); +} diff --git a/zygiskd-new/zygiskd.h b/zygiskd-new/zygiskd.h new file mode 100644 index 0000000..9492a50 --- /dev/null +++ b/zygiskd-new/zygiskd.h @@ -0,0 +1,6 @@ +#ifndef ZYGISKD_H +#define ZYGISKD_H + +void zygiskd_start(void); + +#endif /* ZYGISKD_H */ diff --git a/zygiskd-old/.cargo/config.toml b/zygiskd/.cargo/config.toml similarity index 100% rename from zygiskd-old/.cargo/config.toml rename to zygiskd/.cargo/config.toml diff --git a/zygiskd-old/Cargo.toml b/zygiskd/Cargo.toml similarity index 100% rename from zygiskd-old/Cargo.toml rename to zygiskd/Cargo.toml diff --git a/zygiskd/Makefile b/zygiskd/Makefile deleted file mode 100644 index da3bc8a..0000000 --- a/zygiskd/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -CC := ~/Android/Sdk/ndk/27.0.11902837/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android34-clang - -FILES = root_impl/common.c \ - root_impl/kernelsu.c \ - main.c \ - utils.c \ - -CFLAGS = -D_GNU_SOURCE -Wall -Wextra -Werror -O3 -Iroot_impl -llog - -all: CFLAGS += -DDEBUG=0 -all: - $(CC) $(CFLAGS) $(FILES) -o zygiskd - -debug: CFLAGS += -DDEBUG=1 -debug: - $(CC) $(CFLAGS) $(FILES) -o zygiskd - -clean: - rm -f zygiskd \ No newline at end of file diff --git a/zygiskd-old/build.gradle.kts b/zygiskd/build.gradle.kts similarity index 100% rename from zygiskd-old/build.gradle.kts rename to zygiskd/build.gradle.kts diff --git a/zygiskd/companion.c b/zygiskd/companion.c deleted file mode 100644 index df8387e..0000000 --- a/zygiskd/companion.c +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "dl.h" -#include "utils.h" - -typedef void (*ZygiskCompanionEntryFn)(u_int32_t); - -ZygiskCompanionEntryFn load_module(u_int32_t fd) { - char path[PATH_MAX]; - snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); - - void *handle = android_dlopen(path, RTLD_NOW); - void *entry = dlsym(handle, "zygisk_companion_entry"); - if (entry == NULL) return NULL; - - return (ZygiskCompanionEntryFn)entry; -} - -void *ExecuteNew(void *arg) { - u_int32_t fd = (u_int32_t)arg; - - struct stat st0; - if (fstat(fd) == -1) { - printf("Failed to stat client fd\n"); - - exit(0); - } - entry(fd); - - // Only close client if it is the same file so we don't - // accidentally close a re-used file descriptor. - // This check is required because the module companion - // handler could've closed the file descriptor already. - struct stat st1; - if (fstat(fd) == -1) { - printf("Failed to stat client fd\n"); - - exit(0); - } - - if (st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino) { - close(fd); - } - - return NULL; -} - -void entry(u_int32_t fd) { - printf("companion entry fd=%d\n", fd); - - char name[256]; - read(fd, name, 256); - - int library_fd; - read(fd, &library_fd, sizeof(library_fd)); - - ZygiskCompanionEntryFn entry = load_module(library_fd); - - close(library_fd); - - if (entry == NULL) { - printf("No companion entry for `%s`\n", name); - - write(fd, (void *)0, 1); - - exit(0); - } - - printf("Companion process created for `%s`\n", name); - - write(fd, (void *)1, 1); - - while (1) { - int client_fd; - read(fd, &client_fd, sizeof(client_fd)); - - printf("New companion request from module `%s` fd=`%d`\n", name, client_fd); - - write(fd, (void *)1, 1); - - pthread_t thread; - pthread_create(&thread, NULL, ExecuteNew, (void *)client_fd); - pthread_detach(thread); - - - } -} diff --git a/zygiskd/main.c b/zygiskd/main.c deleted file mode 100644 index e29411a..0000000 --- a/zygiskd/main.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include - -#include "root_impl/common.h" - -#include "utils.h" - -// extern "C" { -// fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32; -// fn __system_property_get(name: *const c_char, value: *mut c_char) -> u32; -// fn __system_property_set(name: *const c_char, value: *const c_char) -> u32; -// fn __system_property_find(name: *const c_char) -> *const c_void; -// fn __system_property_wait( -// info: *const c_void, -// old_serial: u32, -// new_serial: *mut u32, -// timeout: *const libc::timespec, -// ) -> bool; -// fn __system_property_serial(info: *const c_void) -> u32; -// } - -int __android_log_print(int prio, const char *tag, const char *fmt, ...); - -int main(int argc, char *argv[]) { - /* Initialize android logger */ - __android_log_print(ANDROID_LOG_INFO, "zygiskd", "Hello, world! :3"); - - if (argc > 1) { - if (strcmp(argv[0], "companion") == 0) { - /* WIP */ - - return 0; - } - - else if (strcmp(argv[1], "version") == 0) { - printf("ReZygisk Daemon %s\n", ZKSU_VERSION); - - return 0; - } - - else if (strcmp(argv[1], "root") == 0) { - root_impls_setup(); - enum RootImpl impl = get_impl(); - - switch (impl) { - case None: { - printf("No root implementation found.\n"); - - return 1; - } - - case Multiple: { - printf("Multiple root implementations found.\n"); - - return 1; - } - - case KernelSU: { - printf("KernelSU root implementation found.\n"); - - return 0; - } - } - - - return 0; - } - - else { - printf("Usage: zygiskd [companion|version|root]\n"); - - return 0; - } - } - - switch_mount_namespace((pid_t)1); - root_impls_setup(); - __android_log_print(ANDROID_LOG_INFO, "zygiskd", "Root implementation: %d", get_impl()); - - return 0; -} \ No newline at end of file diff --git a/zygiskd/root_impl/kernelsu.h b/zygiskd/root_impl/kernelsu.h deleted file mode 100644 index a4cd565..0000000 --- a/zygiskd/root_impl/kernelsu.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef KERNELSU_H -#define KERNELSU_H - -#include "../constants.h" - -enum RootImplState ksu_get_kernel_su(); - -bool ksu_uid_granted_root(int uid); - -bool ksu_uid_should_umount(int uid); - -bool ksu_uid_is_manager(int uid); - -#endif \ No newline at end of file diff --git a/zygiskd-old/src/companion.rs b/zygiskd/src/companion.rs similarity index 100% rename from zygiskd-old/src/companion.rs rename to zygiskd/src/companion.rs diff --git a/zygiskd-old/src/constants.rs b/zygiskd/src/constants.rs similarity index 100% rename from zygiskd-old/src/constants.rs rename to zygiskd/src/constants.rs diff --git a/zygiskd-old/src/dl.rs b/zygiskd/src/dl.rs similarity index 100% rename from zygiskd-old/src/dl.rs rename to zygiskd/src/dl.rs diff --git a/zygiskd-old/src/main.rs b/zygiskd/src/main.rs similarity index 100% rename from zygiskd-old/src/main.rs rename to zygiskd/src/main.rs diff --git a/zygiskd-old/src/root_impl/apatch.rs b/zygiskd/src/root_impl/apatch.rs similarity index 100% rename from zygiskd-old/src/root_impl/apatch.rs rename to zygiskd/src/root_impl/apatch.rs diff --git a/zygiskd-old/src/root_impl/kernelsu.rs b/zygiskd/src/root_impl/kernelsu.rs similarity index 100% rename from zygiskd-old/src/root_impl/kernelsu.rs rename to zygiskd/src/root_impl/kernelsu.rs diff --git a/zygiskd-old/src/root_impl/magisk.rs b/zygiskd/src/root_impl/magisk.rs similarity index 100% rename from zygiskd-old/src/root_impl/magisk.rs rename to zygiskd/src/root_impl/magisk.rs diff --git a/zygiskd-old/src/root_impl/mod.rs b/zygiskd/src/root_impl/mod.rs similarity index 100% rename from zygiskd-old/src/root_impl/mod.rs rename to zygiskd/src/root_impl/mod.rs diff --git a/zygiskd-old/src/utils.rs b/zygiskd/src/utils.rs similarity index 100% rename from zygiskd-old/src/utils.rs rename to zygiskd/src/utils.rs diff --git a/zygiskd-old/src/zygiskd.rs b/zygiskd/src/zygiskd.rs similarity index 100% rename from zygiskd-old/src/zygiskd.rs rename to zygiskd/src/zygiskd.rs diff --git a/zygiskd/utils.c b/zygiskd/utils.c deleted file mode 100644 index 7c98777..0000000 --- a/zygiskd/utils.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -void switch_mount_namespace(pid_t pid) { - char current_path[PATH_MAX]; - if (getcwd(current_path, PATH_MAX) == NULL) { - /* TODO: Improve error messages */ - perror("getcwd"); - - return; - } - - /* INFO: We will NEVER achieve PATH_MAX value, but this is for ensurance. */ - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "/proc/%d/ns/mnt", pid); - - FILE *mnt_ns = fopen(path, "r"); - if (mnt_ns == NULL) { - /* TODO: Improve error messages */ - perror("fopen"); - - return; - } - - if (setns(fileno(mnt_ns), 0) == -1) { - /* TODO: Improve error messages */ - perror("setns"); - - return; - } - - fclose(mnt_ns); - - if (chdir(current_path) == -1) { - /* TODO: Improve error messages */ - perror("chdir"); - - return; - } -} - -int __system_property_get(const char *, char *); - -void get_property(const char *name, char *output) { - __system_property_get(name, output); -} - -void set_socket_create_context(const char *context) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "/proc/thread-self/attr/sockcreate"); - - FILE *sockcreate = fopen(path, "w"); - if (sockcreate == NULL) { - perror("fopen"); - - return; - } - - if (fwrite(context, 1, strlen(context), sockcreate) != strlen(context)) { - perror("fwrite"); - - return; - } - - fclose(sockcreate); -} - -void get_current_attr(char *output) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "/proc/self/attr/current"); - - FILE *current = fopen(path, "r"); - if (current == NULL) { - perror("fopen"); - - return; - } - - if (fgets(output, PATH_MAX, current) == NULL) { - perror("fgets"); - - return; - } - - fclose(current); -} - -void unix_datagram_sendto(const char *path, const char *buf) { - char current_attr[PATH_MAX]; - get_current_attr(current_attr); - - set_socket_create_context(current_attr); - - struct sockaddr_un addr; - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - - int socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (socket_fd == -1) { - perror("socket"); - - return; - } - - if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - perror("connect"); - - return; - } - - if (sendto(socket_fd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - perror("sendto"); - - return; - } - - set_socket_create_context("u:r:zygote:s0"); - - close(socket_fd); -} - -int chcon(const char *path, const char *context) { - char command[PATH_MAX]; - snprintf(command, PATH_MAX, "chcon %s %s", context, path); - - return system(command); -} - -int unix_listener_from_path(char *path) { - remove(path); - - struct sockaddr_un addr; - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - - int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (socket_fd == -1) { - perror("socket"); - - return -1; - } - - if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - perror("bind"); - - return -1; - } - - if (listen(socket_fd, 2) == -1) { - perror("listen"); - - return -1; - } - - if (chcon(path, "u:object_r:magisk_file:s0") == -1) { - perror("chcon"); - - return -1; - } - - return socket_fd; -} \ No newline at end of file diff --git a/zygiskd/utils.h b/zygiskd/utils.h deleted file mode 100644 index b880d4d..0000000 --- a/zygiskd/utils.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include - -void switch_mount_namespace(pid_t pid); - -void get_property(const char *name, char *output); - -void set_socket_create_context(const char *context); - -void unix_datagram_sendto(const char *path, const char *buf); - -int unix_listener_from_path(char *path); - -#endif /* UTILS_H */ \ No newline at end of file diff --git a/zygiskd/zygiskd b/zygiskd/zygiskd deleted file mode 100755 index 5baaf306c04f32687c94351a106ffa8fa1e96a09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13600 zcmd^GeRNdEb)VgpVG#n$Mz*QH^h}@y46D@#wvg?3!LpHK*~o&_P80WOwY!qGtag{( zCxZYtGR7yII!#!c#H95Hp*g8g>>TRQ1e!DuIB96&CJ+P1C$-(>Bdr{_IdUN`N|Cp} zJ2O`rt@N-H|Ji}JckXZQy>sWz$9r$y=(Be>-{bXo1Sg;Pjv(&*O$rI=f}H`K0SSqE zQHI}Z#cVMJe2K(Vc}NkIsQ5*YiQ00AhjHlbQ|9w{~yjZW?Qh0gGcsg5)&()Omrh=#Txz)$w zOhYWxhpSs{DUGO(u@G~y>uUznV zUGVo@a3Q?%pGQ;0eb`@`w;nM9+j@Bykr}kQd&OmXfg)0gizv;7amlt5@%D%vPsSZ# z+mZEQJM6^POC}TRjAOyb0O?3&)}T17RtGzg>a^3Dc+wH+OvFiutP^(dlZkYvMY_ky z0!Cqn=!`j$by1N`YQ7_tjwMA$JP}K#L^kFmv!WxCNM&Op(iM$oL^_tqq%x>TtyHK3 z3K^%@h9R;KJ<+i)6L(^w15lQ*WF*}yvZ=@#h(uD!WGn*FSTgFQgfgvciA=0J^=M3B z@r#NCwJQnI9tmVqqWRwCcM*eT5sO?jK^dKfKCUu8y^!*K@`4L4?ktj@tN7XazQ=ZU z(jtpwX?ZW~>n@Y{d;`}@y~KkCPR|aU>J41GDvLq}P9uX;lYyJ}p%w$DdoZVm4V>?p zRMuwT(^wd^%fL$wJZ<3mQA3ulH}En;zR$q*EmoFpHSn2+{5Au>+`xAjIL{R--f7_a zkx6Rx8@PF2*<;|d4Ey^Gyu!c_8aO}0QSlK2zuJ&LYT(xx`0EDF&rDRDH}F3&5|7?*l0-lS(;OygQwUb;pue9O9{@)sgB+ zMgw}CM3RZQ;0_$S&Y*$YJk0r@iBHP0gy$Xv!q$(RrbX0{MCsP&a z$z)&?bGHWUWhO649HihFVb_ z2nK?BvFvHcG@z=K6Klu@#eFi)t3Ekdo4Lt74XO4&!-8sO8oI+2U7OZ!()L{EyKNtO zo5t-M80<$u>oB;7K$}2Iu#iPTXM;MRi$ITnegf(&VdN#yI?#ilEugQ1 z9tWL`g>MliK_loE&@|`~(C0u)FxUr)VsJNOA@qZ`fgT0j3%Ut|y98sl41=}{v;}k< zD9?S*hF0O(bff3GvPwbYo#s>t+VU`{Xk6SlGt^XeL-`Bd=e15f;M-BobDQimYmDa$ zVQsh?A;k62bEbnU1Z*{^v~9t*^^A9W$qQ4S_d8{kR?|%2uN{BuO)(cDU&9rJ{Cp`t zv%FDz@^D#YdE-n0DP{jvEywF6)tSfj8R(imo!4@Vp;-747|Wh`4-M9f7_tH7y2rWQr~(;wv!FKCjFZWK`w?=VoP!D2^ zRbVWNakie56_}^xAnZ(B-wy1qWvvmG_WCdU3Ar#0{eF=QrZY`$P`SsJQcEz7qwX=h(@K&BY=(A4}b_zV{ibA2BsJGiwey>+lP#N)0Bot46jcok>?(-`> zyGLLf&mMcox9o-$!+!YW_sn_+ZC~vlx$BwuO#f3Amx*Hw9=9)8o;yzt`YHyTLgDYv zuUxi!WaFX!1F%K)k8C_3ZCMzCl|rmVJBJ3ZdGT6*Z{@1_)nfn1#vk;P9O@Yo)uH{I z_ak39O{`spcGnMAl_)#T_Tr%^V!y2v&6AwqOW!5iSK64 z!1h^O2M$;6yBu-sKWy)7@`$==+n>C0nrGVd1&>W#b>|Gv+Bs-D`7yF_*>2d&kw4fy zy3*tqY=5$~(lc$%eApICwq9$NQEbnl?;MYIA*v)yuH;VyRgB4X;?;<_!&>LfK9G0=aJi@AHYe>=cdd2 zSpy_*0he;k)e`Fm76O)suE+;+#N)nIVZr`ljK4<;g=af(Vcy7gEW1_v&{i#dz`bHS z^)HWMimkNOSCy0XwAALFh0OmH3fFuBc2?o4^ozA2_*_{c)>;@J;{C!Bsbek9ZG|k= zJ;B~!Rqk=OvVFC=4JdmHbx`as>bY2$9y&(x&rc0u4cXk<3mL>^uZ&?y4cbp@%jVWI zzF7+&MVa*X4T_7%5icMM{eg8=SW`Ao5(z7O48 zXd!#WWwOoxS(8h-mF-xZ>vAhQT9pe=Qr6}X6(bw}arecCJXn*wavdp54IO(M{k!1q z8XAuS)@7lW`^)-TWqV6%WqSwj621AU;^lhS?DLAf7;^*E#uo6HcQSty`sEDPtd+oi zqp>FB4|v5pKalghVgPmJ&aYgK`e{u&+#iHL+|J^%YA(AykSi`*$nC(~H`_6YcKAOP zknIqjgLn9+=`pVRjn;iy>!-l4ou09FP(PoB?{k441fEBJv`)D$9PY>7%tT*x8SJUD zuG%qQby)%PWkSp`_Qrhm46v^h*U@o?Smk|N;IDu97no~pQ^Z~sS2ZqA`>q~(-_o4hX%uA^!s&jiUC6CzR8EE^DSpLquy4_4=Px|GXx0ONq}8|dd_XRwZ* zMeOC=zh2F88WZcGPci*A*+JVc%0A_L1m;oE_$wUt(3&#vO~|W0n5Fwb^bW!f^}!cW zMtwl@h5CSa>Vr0{4|EUUKKQD}gklT>h{}u2*N#H=lqU z@msaLoPX3egTWl07t~lqys?L*^2dWYJc_COreF^H;M*%i-<8yd)NZs(^`Rcq)Q19T z2+tzrc%Hf93oC}p+i%ZVct)Z%jW1dDG|D!sGRc1#{4Rt4EAWR5{sr)-4SpAR?;X;% z)c-p8IR-xfe!0Pa6MVbDzXE=5^Y3eZpXLi=@z9=p zG}3po(*OTL5kHwGL`{DrwdPk>*ViwttFK#R-JI^kzT3_1se}WPaER$n5Y`^f#-bK> z1T#x&YU-Yi?J4>RKnXY#cztu0*_xM~?AH?KRC9Jr}{Hw0G_mGlYMRLLSxy zH-O@iM(}rk9`CnmdHxQvTFbAHbWC2ua<5H@tHk^kMihNelB>sq;Qm-5Wn$3$XaMZf zxaeCOe>dMD<%CE|I)-alWHnyK6I>TOrty*@{Bs)Td9KC9HjS4T$v>y@mLeR_{KD&< zA=-32c|CbrIeS@cM>#G-+p>mdAZhrkC+MS^whs1PT4C1&O13Fo~zm@Wc!(5pe{ZSL5RP?HeFpATjx7raOg=A)$#3$A}6ZmBHUM=Nk zh~OWNw{xAuOGTilUQ6N=+dEI<6YItM4*GEn=YGWd7}6NdwKo!uame328GpzHKTPA; zTQ2x~5X;{I`73E$-J}p6&v@@txQ?^jvxP{v#94cce%%E>I8Wn3w~N=q28}ls$v12K;Uf8VjkguauhsY-E#Ij9 z+#>O@cyaD8T<|Zt;9qvZ|61b4_(Z%Yz2YLj-v!5e$E4?V{@DfpnG1f>1%JZ@KjVVG z?ScY?qRDfMjBc zFsbTXIsr?W6n)$lfmoN_kqLLl?5-#znG*q=uYr^lb(ACwguCMrRDjRL^rK2)Jd?81 z;b=6T>_nZ?YI`;-=y{Mntcw6#cEatTT{sG(a*B#b#%ad^o@5{*=B^J^3mb=YGLGGi z2S}X2NyhDPCKK+p*TtPK8(*TGIDK^&k#Hh`kGxzg=0*cG^ixYeb@a1DQ1nKR0;%W$ z4=P+bDJ9UPn8NU#TO^}vYz`~s+k4`PsGaQTZjWW?TRuL>D^G)>b>+&{_PzJFG*fle z^rKziqX8^fR7_2CDe7_JiL6VRZQs+n?Ebs$yB}z@ZB?a;70w}zMPf3D+9l&T{t%Tq zKxKDffF*FgVO=Ji#wjK-daf#(P3gk%C$7@!OaIt$s}FMki%uBWbkZV=UUYiWVokP( zj!W4pST+t)5JwWCCmyvsGhs}Es4Y(>kn9AIfNWQ)2i?=tjWZjLG&vC^B%Z~9O5*rM zW>m<4Tn>k2G3Fv&wzO^2D9NV7k=RE(Ge(W%<6>?H$RMH)irMP;gpK19ax#uTT1KYy zDHHSsX1O|R){~5{w`q7Igxxe{=!n^eIe?~5hseXXLRwKrNia4#GO2D%aHngs<7sx| zryf{#|GjsqRq&(#(sD`{Zd)?tb%ts2eu-XwwX_hlKQa{;>+|~)Q+|(P1-?%*Pw#>B zsLuNQe#Df{a!{f=sBV6L;rGRP!0~Oz0YZV-EE`qA^dj`TX_ReD-@X%e_5nIx(~*O=(u58pWm}JE1uT+ zeEyT)kNEE!SdM9kGn#${lziv@E!I!#K-2i8#O-H4b^#+1*5`ArLwX~X`*xI>*8d>?X`jNZ zpZAgGTdGEWpHtk#_S1d_)gNR5OO#ff>^Y*Jng~j^+2b?YCwEzGB diff --git a/zygiskd/zygiskd.c b/zygiskd/zygiskd.c deleted file mode 100644 index 20ae753..0000000 --- a/zygiskd/zygiskd.c +++ /dev/null @@ -1,353 +0,0 @@ -#include -#include -#include -#include - -#include "root_impl/common.h" -#include "constants.h" -#include "utils.h" - -struct Module { - char *name; - int lib_fd; -} - -struct Context { - struct Module *modules; -} - -enum Architecture { - ARM32, - ARM64, - X86, - X86_64, -} - -static char TMP_PATH[] = "/data/adb/rezygisk"; -static char CONTROLLER_SOCKET[PATH_MAX]; -static char PATH_CP_NAME[PATH_MAX]; - -enum Architecture get_arch() { - char system_arch[PROP_VALUE_MAX]; - get_property("ro.product.cpu.abi", system_arch); - - if (strstr(system_arch, "arm") != NULL) return lp_select(ARM32, ARM64); - if (strstr(system_arch, "x86") != NULL) return lp_select(ARM64, X86_64); - - printf("Unsupported system architecture: %s\n", system_arch); - exit(1); -} - -int create_library_fd(char *so_path) { - int memfd = memfd_create("jit-cache-zygisk", MFD_ALLOW_SEALING); - if (memfd == -1) { - printf("Failed creating memfd: %s\n", strerror(errno)); - return -1; - } - - int file = open(so_path, O_RDONLY); - if (file == -1) { - printf("Failed opening file: %s\n", strerror(errno)); - return -1; - } - - struct stat st; - fstat(file, &st); - ftruncate(memfd, st.st_size); - - void *addr = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0); - if (addr == MAP_FAILED) { - printf("Failed mapping memory: %s\n", strerror(errno)); - return -1; - } - - read(file, addr, st.st_size); - munmap(addr, st.st_size); - close(file); - - unsigned int seals = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL; - if (fcntl(memfd, F_ADD_SEALS, seals) == -1) { - printf("Failed adding seals: %s\n", strerror(errno)); - return -1; - } - - return memfd; -} - -/* WARNING: Dynamic memory based */ -struct Module **load_modules(enum Architecture arch) { - struct Module **modules = malloc(sizeof(struct Module *)); - DIR *dir = opendir(PATH_MODULES_DIR); - - struct dirent *entry; - while ((entry = readdir(dir)) != NULL) { - char *name = entry->d_name; - char so_path[PATH_MAX]; - snprintf(so_path, PATH_MAX, "%s/zygisk/%s.so", PATH_MODULES_DIR, name); - - struct stat st; - if (stat(so_path, &st) == -1) continue; - - char disabled[PATH_MAX]; - snprintf(disabled, PATH_MAX, "%s/disable", PATH_MODULES_DIR); - if (stat(disabled, &st) != -1) continue; - - printf("Loading module `%s`...\n", name); - int lib_fd = create_library_fd(so_path); - if (lib_fd == -1) continue; - - struct Module *module = malloc(sizeof(struct Module)); - module->name = name; - module->lib_fd = lib_fd; - modules = realloc(modules, sizeof(modules) + sizeof(module)); - modules[sizeof(modules)] = module; - } - - return modules; -} - -void free_modules(struct Module **modules) { - for (int i = 0; i < sizeof(modules); i++) { - free(modules[i]); - } - - free(modules); -} - -int create_daemon_socket() { - set_socket_create_context("u:r:zygote:s0"); - int socket_fd = unix_listener_from_path(PATH_CP_NAME); - - return socket_fd; -} - -void zygiskd_start() { - printf("Welcome to ReZygisk %s!\n", ZKSU_VERSION); - - snprintf(CONTROLLER_SOCKET, PATH_MAX, "%s/init_monitor", TMP_PATH); - snprintf(PATH_CP_NAME, PATH_MAX, "%s/%s", TMP_PATH, lp_select("/cp32.sock", "/cp64.sock")); - - Architecture arch = get_arch(); - printf("Daemon architecture: %s\n", arch); - - struct Module **modules = load_modules(arch); - - char *msg = malloc(1); - size_t msg_len = 1; - - switch (get_impl()) { - case KernelSU: { - msg[0] = DAEMON_SET_INFO; - - msg = realloc(msg, strlen("Root: KernelSU, Modules: ") + 1); - memcpy(msg + 1, "Root: KernelSU, Modules: ", strlen("Root: KernelSU, Modules: ")); - msg_len += strlen("Root: KernelSU, Modules: "); - - for (int i = 0; i < sizeof(modules); i++) { - msg = realloc(msg, strlen(modules[i]->name) + strlen(", ") + 1); - memcpy(msg + msg_len, modules[i]->name, strlen(modules[i]->name)); - msg_len += strlen(modules[i]->name); - memcpy(msg + msg_len, ", ", strlen(", ")); - msg_len += strlen(", "); - - free(modules[i]); - } - } - default: { - msg[0] = DAEMON_SET_ERROR_INFO; - - msg = realloc(msg, strlen("Invalid root implementation") + 1); - memcpy(msg + 1, "Invalid root implementation", strlen("Invalid root implementation")); - } - } - - msg = realloc(msg, msg_len + 1); - msg[msg_len] = '\0'; - - unix_datagram_sendto(CONTROLLER_SOCKET, msg); - - int socket_fd = create_daemon_socket(); - if (socket_fd == -1) { - printf("Failed creating daemon socket: %s\n", strerror(errno)); - - return; - } - - while (1) { - struct sockaddr_un addr; - socklen_t addr_len = sizeof(addr); - int client_fd = accept(socket_fd, (struct sockaddr *) &addr, &addr_len); - if (client_fd == -1) { - printf("Failed accepting client: %s\n", strerror(errno)); - - return; - } - - char action; - read(client_fd, &action, 1); - - switch (action) { - case DAEMON_PING_HEARTBEAT: { - char value = ZYGOTE_INJECTED; - unix_datagram_sendto(CONTROLLER_SOCKET, &value); - } - case DAEMON_ZYGOTE_RESTART: { - printf("Zygote restarted, clean up companions\n"); - - free_modules(modules); - - /* companion code */ - } - case DAEMON_SYSTEM_SERVER_STARTED: { - char value = SYSTEM_SERVER_STARTED; - unix_datagram_sendto(CONTROLLER_SOCKET, &value); - } - default: { - // WIP - } - } - } -} - -void spawn_companion(char *name, int lib_fd) { - /* Creates 2 connected unix streams */ - int sockets[2]; - socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); - - int daemon_fd = sockets[0]; - int companion_fd = sockets[1]; - - pid_t pid = fork(); - if (pid == -1) { - printf("Failed forking: %s\n", strerror(errno)); - - return; - } else if (pid > 0) { - close(companion_fd); - - int status; - waitpid(pid, &status, 0); - - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - write(daemon_fd, name, strlen(name)); - write(daemon_fd, &lib_fd, sizeof(lib_fd)); - - int response; - read(daemon_fd, &response, 1); - - if (response == 0) { - printf("No companion spawned for %s because it has no entry\n", name); - } else if (response == 1) { - printf("Spawned companion for %s\n", name); - } else { - printf("Invalid companion response\n"); - } - } else { - printf("Exited with status %d\n", status); - } - } else { - fcntl(companion_fd, F_SETFD, 0); - } - - char *args[] = { "zygiskd", "companion", companion_fd, NULL }; - execv("/system/bin/zygiskd", args); - - exit(0); -} - -void handle_daemon_action(enum DaemonSocketAction action, int stream_fd, struct Context *context) { - switch (action) { - case RequestLogcatFd: { - while (1) { - char level; - read(stream_fd, &level, 1); - - char tag[PATH_MAX]; - read(stream_fd, tag, PATH_MAX); - - char message[PATH_MAX]; - read(stream_fd, message, PATH_MAX); - - __android_log_print(level, tag, message); - } - } - case GetProcessFlags: { - int uid; - read(stream_fd, &uid, sizeof(uid)); - - int flags = 0; - if (uid_is_manager(uid)) { - flags |= PROCESS_IS_MANAGER; - } else { - if (uid_granted_root(uid)) { - flags |= PROCESS_GRANTED_ROOT; - } - if (uid_should_umount(uid)) { - flags |= PROCESS_ON_DENYLIST; - } - } - - switch (get_impl()) { - case KernelSU: { - flags |= PROCESS_ROOT_IS_KSU; - } - // case Magisk: { - // flags |= PROCESS_ROOT_IS_MAGISK; - // } - // case APatch: { - // flags |= PROCESS_ROOT_IS_APATCH; - // } - } - - write(stream_fd, &flags, sizeof(flags)); - } - case GetInfo: { - int flags = 0; - - switch (get_impl()) { - case KernelSU: { - flags |= PROCESS_ROOT_IS_KSU; - } - // case Magisk: { - // flags |= PROCESS_ROOT_IS_MAGISK; - // } - // case APatch: { - // flags |= PROCESS_ROOT_IS_APATCH; - // } - } - - write(stream_fd, &flags, sizeof(flags)); - - int pid = getpid(); - write(stream_fd, &pid, sizeof(pid)); - } - case ReadModules: { - int len = sizeof(context->modules); - write(stream_fd, &len, sizeof(len)); - - for (int i = 0; i < len; i++) { - write(stream_fd, context->modules[i]->name, strlen(context->modules[i]->name)); - send_fd(stream_fd, context->modules[i]->lib_fd); - } - } - case RequestCompanionSocket: { - /* WIP */ - - break; - } - case GetModuleDir: { - int index; - read(stream_fd, &index, sizeof(index)); - - char dir[PATH_MAX]; - snprintf(dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context->modules[index]->name); - int dir_fd = open(dir, O_RDONLY); - - send_fd(stream_fd, dir_fd); - } - default: { - // WIP - } - } -} -