diff --git a/loader/src/common/daemon.cpp b/loader/src/common/daemon.cpp index 31eb37f..34a188c 100644 --- a/loader/src/common/daemon.cpp +++ b/loader/src/common/daemon.cpp @@ -1,221 +1,263 @@ #include #include #include +#include +#include +#include +#include #include "daemon.h" #include "dl.h" #include "socket_utils.h" namespace zygiskd { - static std::string TMP_PATH; - void Init(const char *path) { - TMP_PATH = path; + static std::string TMP_PATH; + void Init(const char *path) { + TMP_PATH = path; + } + + std::string GetTmpPath() { + return TMP_PATH; + } + + int Connect(uint8_t retry) { + retry++; + + int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + .sun_path = { 0 } + }; + + auto socket_path = TMP_PATH + kCPSocketName; + strcpy(addr.sun_path, socket_path.c_str()); + socklen_t socklen = sizeof(addr); + + while (--retry) { + int r = connect(fd, (struct sockaddr *)&addr, socklen); + if (r == 0) return fd; + if (retry) { + PLOGE("Retrying to connect to zygiskd, sleep 1s"); + + sleep(1); + } } - std::string GetTmpPath() { - return TMP_PATH; + close(fd); + + return -1; + } + + bool PingHeartbeat() { + int fd = Connect(5); + if (fd == -1) { + PLOGE("Connect to zygiskd"); + + return false; } - int Connect(uint8_t retry) { - int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - struct sockaddr_un addr = { - .sun_family = AF_UNIX, - .sun_path = { 0 }, - }; + socket_utils::write_u8(fd, (uint8_t) SocketAction::PingHeartBeat); - auto socket_path = TMP_PATH + kCPSocketName; - strcpy(addr.sun_path, socket_path.c_str()); - socklen_t socklen = sizeof(addr); + close(fd); - while (retry--) { - int r = connect(fd, reinterpret_cast(&addr), socklen); - if (r == 0) return fd; - if (retry) { - PLOGE("Retrying to connect to zygiskd, sleep 1s"); - sleep(1); - } - } + return true; + } + + int RequestLogcatFd() { + int fd = Connect(1); + if (fd == -1) { + PLOGE("RequestLogcatFd"); + + return -1; + } + + socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestLogcatFd); + + return fd; + } + + uint32_t GetProcessFlags(uid_t uid) { + int fd = Connect(1); + if (fd == -1) { + PLOGE("GetProcessFlags"); + + return 0; + } + + socket_utils::write_u8(fd, (uint8_t) SocketAction::GetProcessFlags); + socket_utils::write_u32(fd, uid); + + uint32_t res = socket_utils::read_u32(fd); + + close(fd); + + return res; + } + + std::vector ReadModules() { + std::vector modules; + int fd = Connect(1); + if (fd == -1) { + PLOGE("ReadModules"); + + return modules; + } + + socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadModules); + size_t len = socket_utils::read_usize(fd); + for (size_t i = 0; i < len; i++) { + std::string name = socket_utils::read_string(fd); + int module_fd = socket_utils::recv_fd(fd); + modules.emplace_back(name, module_fd); + } + + close(fd); + + return modules; + } + + int ConnectCompanion(size_t index) { + int fd = Connect(1); + if (fd == -1) { + PLOGE("ConnectCompanion"); + + return -1; + } + + socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestCompanionSocket); + socket_utils::write_usize(fd, index); + + uint8_t res = socket_utils::read_u8(fd); + + if (res == 1) return fd; + else { + close(fd); + + return -1; + } + } + + int GetModuleDir(size_t index) { + int fd = Connect(1); + if (fd == -1) { + PLOGE("GetModuleDir"); + + return -1; + } + + socket_utils::write_u8(fd, (uint8_t) SocketAction::GetModuleDir); + socket_utils::write_usize(fd, index); + int nfd = socket_utils::recv_fd(fd); + + close(fd); + + return nfd; + } + + void ZygoteRestart() { + int fd = Connect(1); + if (fd == -1) { + if (errno == ENOENT) LOGD("Could not notify ZygoteRestart (maybe it hasn't been created)"); + else PLOGE("Could not notify ZygoteRestart"); + + return; + } + + if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart)) + PLOGE("Failed to request ZygoteRestart"); + + close(fd); + } + + void SystemServerStarted() { + int fd = Connect(1); + if (fd == -1) PLOGE("Failed to report system server started"); + else { + if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::SystemServerStarted)) + PLOGE("Failed to report system server started"); + } + + close(fd); + } + + void GetInfo(struct zygote_info *info) { + /* TODO: Optimize and avoid re-connect twice here */ + int fd = Connect(1); + + if (fd != -1) { + info->running = true; + + socket_utils::write_u8(fd, (uint8_t) SocketAction::GetInfo); + + int flags = socket_utils::read_u32(fd); + + if (flags & (1 << 27)) { + info->root_impl = ZYGOTE_ROOT_IMPL_APATCH; + } else if (flags & (1 << 29)) { + info->root_impl = ZYGOTE_ROOT_IMPL_KERNELSU; + } else if (flags & (1 << 30)) { + info->root_impl = ZYGOTE_ROOT_IMPL_MAGISK; + } else { + info->root_impl = ZYGOTE_ROOT_IMPL_NONE; + } + + info->pid = socket_utils::read_u32(fd); + + info->modules = (struct zygote_modules *)malloc(sizeof(struct zygote_modules)); + if (info->modules == NULL) { + info->modules->modules_count = 0; close(fd); - return -1; - } - bool PingHeartbeat() { - UniqueFd fd = Connect(5); - if (fd == -1) { - PLOGE("Connect to zygiskd"); - return false; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::PingHeartBeat); - return true; - } + return; + } - int RequestLogcatFd() { - int fd = Connect(1); - if (fd == -1) { - PLOGE("RequestLogcatFd"); - return -1; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestLogcatFd); - return fd; - } + info->modules->modules_count = socket_utils::read_usize(fd); - uint32_t GetProcessFlags(uid_t uid) { - UniqueFd fd = Connect(1); - if (fd == -1) { - PLOGE("GetProcessFlags"); - return 0; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::GetProcessFlags); - socket_utils::write_u32(fd, uid); + if (info->modules->modules_count == 0) { + info->modules->modules = NULL; - return socket_utils::read_u32(fd); - } + close(fd); - std::vector ReadModules() { - std::vector modules; - UniqueFd fd = Connect(1); - if (fd == -1) { - PLOGE("ReadModules"); - return modules; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadModules); - size_t len = socket_utils::read_usize(fd); - for (size_t i = 0; i < len; i++) { - std::string name = socket_utils::read_string(fd); - int module_fd = socket_utils::recv_fd(fd); - modules.emplace_back(name, module_fd); - } - return modules; - } + return; + } - int ConnectCompanion(size_t index) { - int fd = Connect(1); - if (fd == -1) { - PLOGE("ConnectCompanion"); - return -1; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::RequestCompanionSocket); - socket_utils::write_usize(fd, index); - if (socket_utils::read_u8(fd) == 1) { - return fd; + info->modules->modules = (char **)malloc(sizeof(char *) * info->modules->modules_count); + if (info->modules->modules == NULL) { + free(info->modules); + info->modules = NULL; + info->modules->modules_count = 0; + + close(fd); + + return; + } + + for (size_t i = 0; i < info->modules->modules_count; i++) { + /* INFO by ThePedroo: Ugly solution to read with std::string existance (temporary) */ + std::string name = socket_utils::read_string(fd); + + char module_path[PATH_MAX]; + snprintf(module_path, sizeof(module_path), "/data/adb/modules/%s/module.prop", name.c_str()); + + FILE *module_prop = fopen(module_path, "r"); + if (module_prop == NULL) { + info->modules->modules[i] = strdup(name.c_str()); } else { - close(fd); - return -1; - } - } + char line[1024]; + while (fgets(line, sizeof(line), module_prop) != NULL) { + if (strncmp(line, "name=", 5) == 0) { + info->modules->modules[i] = strndup(line + 5, strlen(line) - 6); - int GetModuleDir(size_t index) { - UniqueFd fd = Connect(1); - if (fd == -1) { - PLOGE("GetModuleDir"); - return -1; - } - socket_utils::write_u8(fd, (uint8_t) SocketAction::GetModuleDir); - socket_utils::write_usize(fd, index); - return socket_utils::recv_fd(fd); - } - - void ZygoteRestart() { - UniqueFd fd = Connect(1); - if (fd == -1) { - if (errno == ENOENT) { - LOGD("Could not notify ZygoteRestart (maybe it hasn't been created)"); - } else { - PLOGE("Could not notify ZygoteRestart"); + break; } - return; - } - if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::ZygoteRestart)) { - PLOGE("Failed to request ZygoteRestart"); - } - } - - void SystemServerStarted() { - UniqueFd fd = Connect(1); - if (fd == -1) { - PLOGE("Failed to report system server started"); - } else { - if (!socket_utils::write_u8(fd, (uint8_t) SocketAction::SystemServerStarted)) { - PLOGE("Failed to report system server started"); - } - } - } - - void GetInfo(struct zygote_info *info) { - /* TODO: Optimize and avoid re-connect twice here */ - int fd = Connect(1); - - if (fd != -1) { - socket_utils::write_u8(fd, (uint8_t) SocketAction::GetInfo); - - int flags = socket_utils::read_u32(fd); - - if (flags & (1 << 27)) { - info->root_impl = ZYGOTE_ROOT_IMPL_APATCH; - } else if (flags & (1 << 29)) { - info->root_impl = ZYGOTE_ROOT_IMPL_KERNELSU; - } else if (flags & (1 << 30)) { - info->root_impl = ZYGOTE_ROOT_IMPL_MAGISK; - } else { - info->root_impl = ZYGOTE_ROOT_IMPL_NONE; - } - - info->modules = (struct zygote_modules *)malloc(sizeof(struct zygote_modules)); - if (info->modules == NULL) { - info->modules->modules_count = 0; - - close(fd); - - return; - } - - info->modules->modules_count = socket_utils::read_usize(fd); - - if (info->modules->modules_count == 0) { - info->modules->modules = NULL; - - close(fd); - - return; - } - - info->modules->modules = (char **)malloc(sizeof(char *) * info->modules->modules_count); - if (info->modules->modules == NULL) { - free(info->modules); - info->modules = NULL; - info->modules->modules_count = 0; - - close(fd); - - return; - } - - for (size_t i = 0; i < info->modules->modules_count; i++) { - /* INFO by ThePedroo: Ugly solution to read with std::string existance (temporary) */ - std::string name = socket_utils::read_string(fd); - - char module_path[PATH_MAX]; - snprintf(module_path, sizeof(module_path), "/data/adb/modules/%s/module.prop", name.c_str()); - - FILE *module_prop = fopen(module_path, "r"); - if (module_prop == NULL) { - info->modules->modules[i] = strdup(name.c_str()); - } else { - char line[1024]; - while (fgets(line, sizeof(line), module_prop) != NULL) { - if (strncmp(line, "name=", 5) == 0) { - info->modules->modules[i] = strndup(line + 5, strlen(line) - 6); - - break; - } - } - - fclose(module_prop); } - } - close(fd); - } else info->running = false; - } + fclose(module_prop); + } + } + + close(fd); + } else info->running = false; + } } diff --git a/loader/src/common/socket_utils.cpp b/loader/src/common/socket_utils.cpp index d4a9f1d..730d49d 100644 --- a/loader/src/common/socket_utils.cpp +++ b/loader/src/common/socket_utils.cpp @@ -5,131 +5,133 @@ #include "socket_utils.h" namespace socket_utils { + ssize_t xread(int fd, void* buf, size_t count) { + size_t read_sz = 0; + ssize_t ret; + do { + ret = read(fd, (std::byte*) buf + read_sz, count - read_sz); + if (ret < 0) { + if (errno == EINTR) continue; + PLOGE("read"); + return ret; + } + read_sz += ret; + } while (read_sz != count && ret != 0); + if (read_sz != count) { + PLOGE("read (%zu != %zu)", count, read_sz); + } + return read_sz; + } - ssize_t xread(int fd, void* buf, size_t count) { - size_t read_sz = 0; - ssize_t ret; - do { - ret = read(fd, (std::byte*) buf + read_sz, count - read_sz); - if (ret < 0) { - if (errno == EINTR) continue; - PLOGE("read"); - return ret; - } - read_sz += ret; - } while (read_sz != count && ret != 0); - if (read_sz != count) { - PLOGE("read (%zu != %zu)", count, read_sz); + size_t xwrite(int fd, const void* buf, size_t count) { + size_t write_sz = 0; + ssize_t ret; + do { + ret = write(fd, (std::byte*) buf + write_sz, count - write_sz); + if (ret < 0) { + if (errno == EINTR) continue; + PLOGE("write"); + return write_sz; } - return read_sz; + write_sz += ret; + } while (write_sz != count && ret != 0); + if (write_sz != count) { + PLOGE("write (%zu != %zu)", count, write_sz); } + return write_sz; + } - size_t xwrite(int fd, const void* buf, size_t count) { - size_t write_sz = 0; - ssize_t ret; - do { - ret = write(fd, (std::byte*) buf + write_sz, count - write_sz); - if (ret < 0) { - if (errno == EINTR) continue; - PLOGE("write"); - return write_sz; - } - write_sz += ret; - } while (write_sz != count && ret != 0); - if (write_sz != count) { - PLOGE("write (%zu != %zu)", count, write_sz); - } - return write_sz; - } + ssize_t xrecvmsg(int sockfd, struct msghdr* msg, int flags) { + int rec = recvmsg(sockfd, msg, flags); + if (rec < 0) PLOGE("recvmsg"); + return rec; + } - ssize_t xrecvmsg(int sockfd, struct msghdr* msg, int flags) { - int rec = recvmsg(sockfd, msg, flags); - if (rec < 0) PLOGE("recvmsg"); - return rec; - } + template + inline T read_exact_or(int fd, T fail) { + T res; + return sizeof(T) == xread(fd, &res, sizeof(T)) ? res : fail; + } - void* recv_fds(int sockfd, char* cmsgbuf, size_t bufsz, int cnt) { - iovec iov = { - .iov_base = &cnt, - .iov_len = sizeof(cnt), - }; - msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = cmsgbuf, - .msg_controllen = bufsz - }; + template + inline bool write_exact(int fd, T val) { + return sizeof(T) == xwrite(fd, &val, sizeof(T)); + } - xrecvmsg(sockfd, &msg, MSG_WAITALL); - cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + uint8_t read_u8(int fd) { + return read_exact_or(fd, 0); + } - if (msg.msg_controllen != bufsz || - cmsg == nullptr || - // TODO: pass from rust: 20, expected: 16 - // cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) || - cmsg->cmsg_level != SOL_SOCKET || - cmsg->cmsg_type != SCM_RIGHTS) { - return nullptr; - } + uint32_t read_u32(int fd) { + return read_exact_or(fd, 0); + } - return CMSG_DATA(cmsg); - } + size_t read_usize(int fd) { + return read_exact_or(fd, 0); + } - template - inline T read_exact_or(int fd, T fail) { - T res; - return sizeof(T) == xread(fd, &res, sizeof(T)) ? res : fail; - } + bool write_usize(int fd, size_t val) { + return write_exact(fd, val); + } - template - inline bool write_exact(int fd, T val) { - return sizeof(T) == xwrite(fd, &val, sizeof(T)); - } + std::string read_string(int fd) { + size_t len = read_usize(fd); - uint8_t read_u8(int fd) { - return read_exact_or(fd, 0); - } + char buf[len + 1]; + xread(fd, buf, len); - uint32_t read_u32(int fd) { - return read_exact_or(fd, 0); - } + buf[len] = '\0'; - size_t read_usize(int fd) { - return read_exact_or(fd, 0); - } + return buf; + } - bool write_usize(int fd, size_t val) { - return write_exact(fd, val); - } + bool write_u8(int fd, uint8_t val) { + return write_exact(fd, val); + } - std::string read_string(int fd) { - auto len = read_usize(fd); - char buf[len + 1]; - buf[len] = '\0'; - xread(fd, buf, len); - return buf; - } + void* recv_fds(int sockfd, char* cmsgbuf, size_t bufsz, int cnt) { + iovec iov = { + .iov_base = &cnt, + .iov_len = sizeof(cnt), + }; + msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = bufsz + }; - bool write_u8(int fd, uint8_t val) { - return write_exact(fd, val); - } + xrecvmsg(sockfd, &msg, MSG_WAITALL); + cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - bool write_u32(int fd, uint32_t val) { - return write_exact(fd, val); - } + if (msg.msg_controllen != bufsz || + cmsg == nullptr || + // TODO: pass from rust: 20, expected: 16 + // cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + return nullptr; + } - bool write_string(int fd, std::string_view str) { - return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size()); - } + return CMSG_DATA(cmsg); + } int recv_fd(int sockfd) { - char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; - void* data = recv_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), 1); - if (data == nullptr) return -1; + void* data = recv_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), 1); + if (data == nullptr) return -1; - int result; - memcpy(&result, data, sizeof(int)); - return result; - } + int result; + memcpy(&result, data, sizeof(int)); + return result; + } + + bool write_u32(int fd, uint32_t val) { + return write_exact(fd, val); + } + + bool write_string(int fd, std::string_view str) { + return write_usize(fd, str.size()) && str.size() == xwrite(fd, str.data(), str.size()); + } } diff --git a/zygiskd/build.gradle.kts b/zygiskd/build.gradle.kts index e7bd970..d9a6410 100644 --- a/zygiskd/build.gradle.kts +++ b/zygiskd/build.gradle.kts @@ -15,7 +15,7 @@ fun getLatestNDKPath(): String { } // get 2nd latest version - val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(1) + val ndkVersion = ndkDir.toFile().listFiles().filter { it.isDirectory }.map { it.name }.sorted().reversed().getOrNull(2) return ndkPath + "/" + ndkVersion } diff --git a/zygiskd/src/companion.c b/zygiskd/src/companion.c index b45b3b6..9f12720 100644 --- a/zygiskd/src/companion.c +++ b/zygiskd/src/companion.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,11 @@ typedef void (*zygisk_companion_entry_func)(int); +struct companion_module_thread_args { + int fd; + zygisk_companion_entry_func entry; +}; + zygisk_companion_entry_func load_module(int fd) { char path[PATH_MAX]; snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); @@ -30,101 +36,100 @@ zygisk_companion_entry_func load_module(int fd) { return (zygisk_companion_entry_func)entry; } -void *call_entry(void *restrict arg) { - int fd = *((int *)arg); +void *entry_thread(void *arg) { + struct companion_module_thread_args *args = (struct companion_module_thread_args *)arg; + + int fd = args->fd; + zygisk_companion_entry_func module_entry = args->entry; struct stat st0; - if (fstat(fd, &st0) == -1) { - LOGE("Failed to stat client fd\n"); + fstat(fd, &st0); - free(arg); + LOGI("New companion thread (inside the thread!).\n - Client fd: %d\n", fd); - exit(0); - } - entry(fd); + module_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. + /* TODO: Is this even necessary? */ struct stat st1; - if (fstat(fd, &st1) == -1) { - LOGE("Failed to stat client fd\n"); + if (fstat(fd, &st1) != -1) { + if (st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino) { + close(fd); - free(arg); - - exit(0); + LOGI("Client fd has been replaced. Bye!\n"); + } } - if (st0.st_dev != st1.st_dev || st0.st_ino != st1.st_ino) { - close(fd); - } + free(args); - free(arg); + pthread_exit(NULL); return NULL; } void entry(int fd) { - LOGI("companion entry fd: |%d|\n", fd); + LOGI("New companion entry.\n - Client fd: %d\n", fd); - char name[256 + 1]; - ssize_t ret = read_string(fd, name, sizeof(name) - 1); - if (ret == -1) return; + char name[256]; + ssize_t ret = read_string(fd, name, sizeof(name)); + if (ret == -1) { + LOGE("Failed to read module name\n"); - 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); - - zygisk_companion_entry_func 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); - - uint8_t response = 0; + uint8_t response = 2; write(fd, &response, sizeof(response)); exit(0); - - return; } - LOGI("Companion process created for: %s\n", name); + LOGI(" - Module name: `%.*s`\n", (int)ret, name); - uint8_t response = 1; - write(fd, &response, sizeof(response)); + int library_fd = gread_fd(fd); + if (library_fd == -1) { + LOGE("Failed to receive library fd\n"); + + uint8_t response = 2; + write(fd, &response, sizeof(response)); + + exit(0); + } + + LOGI(" - Library fd: %d\n", library_fd); + + zygisk_companion_entry_func module_entry = load_module(library_fd); + close(library_fd); + + if (module_entry == NULL) { + LOGI("No companion module entry for module: %.*s\n", (int)ret, name); + + write_int(fd, 0); + + exit(0); + } else { + write_int(fd, 1); + } while (1) { if (!check_unix_socket(fd, true)) { - LOGI("Something went wrong. Bye!\n"); + LOGI("Something went wrong in companion. Bye!\n"); exit(0); break; } - int *client_fd = malloc(sizeof(int)); - recv_fd(fd, client_fd); + struct companion_module_thread_args *args = malloc(sizeof(struct companion_module_thread_args)); + args->entry = module_entry; + + if ((args->fd = gread_fd(fd)) == -1) { + LOGE("Failed to receive client fd\n"); - LOGI("New companion request from module \"%s\" with fd \"%d\"\n", name, *client_fd); + exit(0); + } - write(fd, &response, sizeof(response)); - - LOGI("Creating new thread for companion request\n"); + LOGI("New companion request.\n - Module name: %.*s\n - Client fd: %d\n", (int)ret, name, args->fd); + write_uint8_t(args->fd, 1); + pthread_t thread; - pthread_create(&thread, NULL, call_entry, (void *)client_fd); - pthread_detach(thread); + pthread_create(&thread, NULL, entry_thread, args); } } diff --git a/zygiskd/src/dl.c b/zygiskd/src/dl.c index b7cba7b..37aeec2 100644 --- a/zygiskd/src/dl.c +++ b/zygiskd/src/dl.c @@ -1,29 +1,51 @@ +#include #include - -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "companion.h" +#include "dl.h" +#include "utils.h" #define ANDROID_NAMESPACE_TYPE_SHARED 0x2 #define ANDROID_DLEXT_USE_NAMESPACE 0x200 -struct AndroidNamespace { - u_int8_t _unused[0]; -}; +typedef struct AndroidNamespace { + unsigned char _unused[0]; +} AndroidNamespace; -struct AndroidDlextinfo { - u_int64_t flags; +typedef struct AndroidDlextinfo { + uint64_t flags; void *reserved_addr; size_t reserved_size; int relro_fd; int library_fd; off64_t library_fd_offset; - struct AndroidNamespace *library_namespace; -}; + AndroidNamespace *library_namespace; +} AndroidDlextinfo; -void *android_dlopen_ext(const char *filename, int flags, const struct AndroidDlextinfo *extinfo); +extern void *android_dlopen_ext(const char *filename, int flags, const AndroidDlextinfo *extinfo); -void *android_dlopen(char *restrict path, uint32_t flags) { +typedef AndroidNamespace *(*AndroidCreateNamespaceFn)( + const char *name, + const char *ld_library_path, + const char *default_library_path, + uint64_t type, + const char *permitted_when_isolated_path, + AndroidNamespace *parent, + const void *caller_addr +); + +void *android_dlopen(char *path, int flags) { char *dir = dirname(path); struct AndroidDlextinfo info = { .flags = 0, @@ -35,24 +57,32 @@ void *android_dlopen(char *restrict path, uint32_t flags) { .library_namespace = NULL, }; - void *android_create_namespace_fn = dlsym(RTLD_DEFAULT, "__loader_android_create_namespace"); + void *handle = dlsym(RTLD_DEFAULT, "__loader_android_create_namespace"); + AndroidCreateNamespaceFn android_create_namespace_fn = (AndroidCreateNamespaceFn)handle; - if (android_create_namespace_fn != NULL) { - void *ns = ((void *(*)(const char *, const char *, const char *, u_int32_t, void *, void *, void *))android_create_namespace_fn)( - path, - dir, - NULL, - ANDROID_NAMESPACE_TYPE_SHARED, - NULL, - NULL, - (void *)&android_dlopen - ); + AndroidNamespace *ns = android_create_namespace_fn( + path, + dir, + NULL, + ANDROID_NAMESPACE_TYPE_SHARED, + NULL, + NULL, + (const void *)&android_dlopen + ); - if (ns != NULL) { - info.flags = ANDROID_DLEXT_USE_NAMESPACE; - info.library_namespace = ns; - } + if (ns != NULL) { + info.flags = ANDROID_DLEXT_USE_NAMESPACE; + info.library_namespace = ns; + + LOGI("Open %s with namespace %p\n", path, (void *)ns); + } else { + LOGI("Cannot create namespace for %s\n", path); } - return android_dlopen_ext(path, flags, &info); + void *result = android_dlopen_ext(path, flags, &info); + if (result == NULL) { + LOGE("Failed to dlopen %s: %s\n", path, dlerror()); + } + + return result; } diff --git a/zygiskd/src/dl.h b/zygiskd/src/dl.h index 2c32160..97ba83e 100644 --- a/zygiskd/src/dl.h +++ b/zygiskd/src/dl.h @@ -1,6 +1,6 @@ #ifndef DL_H #define DL_H -void *android_dlopen(char *restrict path, u_int32_t flags); +void *android_dlopen(char *path, int flags); #endif /* DL_H */ diff --git a/zygiskd/src/main.c b/zygiskd/src/main.c index f6f9073..7c9a857 100644 --- a/zygiskd/src/main.c +++ b/zygiskd/src/main.c @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { return 1; } root_impls_setup(); - zygiskd_start(); + zygiskd_start(argv); return 0; } diff --git a/zygiskd/src/root_impl/apatch.c b/zygiskd/src/root_impl/apatch.c index ce597d4..7db9389 100644 --- a/zygiskd/src/root_impl/apatch.c +++ b/zygiskd/src/root_impl/apatch.c @@ -57,7 +57,7 @@ bool _apatch_get_package_config(struct packages_config *restrict config) { return false; } - char line[1024]; + char line[1024 * 2]; /* INFO: Skip the CSV header */ fgets(line, sizeof(line), fp); diff --git a/zygiskd/src/utils.c b/zygiskd/src/utils.c index 19d8e52..bbbe767 100644 --- a/zygiskd/src/utils.c +++ b/zygiskd/src/utils.c @@ -18,6 +18,10 @@ #include "utils.h" +/* INFO 50ms wait */ +// #define ALLOW_WAIT_ON_DEBUG() usleep(500 * 1000) +#define ALLOW_WAIT_ON_DEBUG() {} + bool switch_mount_namespace(pid_t pid) { char path[PATH_MAX]; snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); @@ -192,82 +196,114 @@ int unix_listener_from_path(char *restrict path) { 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; +ssize_t gwrite_fd(int fd, int sendfd) { + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char buf[1] = { 0 }; + struct iovec iov = { - .iov_base = &cnt, - .iov_len = sizeof(cnt) + .iov_base = buf, + .iov_len = 1 }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = control_buf, - .msg_controllen = sizeof(control_buf) + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf) }; struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sendfd, sizeof(int)); - ssize_t sent_bytes = sendmsg(sockfd, &msg, 0); - if (sent_bytes == -1) { - LOGE("Failed to send fd: %s\n", strerror(errno)); + ssize_t ret = sendmsg(fd, &msg, 0); + if (ret == -1) { + LOGE("sendmsg: %s\n", strerror(errno)); return -1; } - return sent_bytes; + return ret; } -ssize_t recv_fd(int sockfd, int *restrict fd) { - char control_buf[CMSG_SPACE(sizeof(int))]; - memset(control_buf, 0, sizeof(control_buf)); - - int cnt = 1; +int gread_fd(int fd) { + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char buf[1] = { 0 }; + struct iovec iov = { - .iov_base = &cnt, - .iov_len = sizeof(cnt) + .iov_base = buf, + .iov_len = 1 }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = control_buf, - .msg_controllen = sizeof(control_buf) + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf) }; - ssize_t received_bytes = recvmsg(sockfd, &msg, 0); - if (received_bytes == -1) { - LOGE("Failed to read fd: %s\n", strerror(errno)); + ssize_t ret = recvmsg(fd, &msg, 0); + if (ret == -1) { + LOGE("recvmsg: %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 *restrict 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)); + if (cmsg == NULL) { + LOGE("CMSG_FIRSTHDR: %s\n", strerror(errno)); return -1; } - written_bytes = write(fd, str, len); - if ((size_t)written_bytes != len) { + int sendfd; + memcpy(&sendfd, CMSG_DATA(cmsg), sizeof(int)); + + return sendfd; +} + +#define write_func(type) \ + ssize_t write_## type(int fd, type val) { \ + ALLOW_WAIT_ON_DEBUG(); \ + \ + return write(fd, &val, sizeof(type)); \ + } + +#define read_func(type) \ + ssize_t read_## type(int fd, type *val) { \ + return read(fd, val, sizeof(type)); \ + } + +write_func(int) +read_func(int) + +write_func(size_t) +read_func(size_t) + +write_func(uint32_t) +read_func(uint32_t) + +write_func(uint8_t) +read_func(uint8_t) + +ssize_t write_string(int fd, const char *restrict str) { + size_t len[1]; + len[0] = strlen(str); + + ALLOW_WAIT_ON_DEBUG(); + + ssize_t written_bytes = write(fd, &len, sizeof(size_t)); + if (written_bytes != sizeof(size_t)) { + LOGE("Failed to write string length: Not all bytes were written (%zd != %zu).\n", written_bytes, sizeof(size_t)); + + return -1; + } + + written_bytes = write(fd, str, len[0]); + if ((size_t)written_bytes != len[0]) { LOGE("Failed to write string: Not all bytes were written.\n"); return -1; @@ -279,9 +315,9 @@ ssize_t write_string(int fd, const char *restrict str) { ssize_t read_string(int fd, char *restrict str, size_t len) { size_t str_len_buf[1]; - ssize_t read_bytes = read(fd, &str_len_buf, sizeof(str_len_buf)); - if (read_bytes != (ssize_t)sizeof(str_len_buf)) { - LOGE("Failed to read string length: %s\n", strerror(errno)); + ssize_t read_bytes = read(fd, &str_len_buf, sizeof(size_t)); + if (read_bytes != (ssize_t)sizeof(size_t)) { + LOGE("Failed to read string length: Not all bytes were read (%zd != %zu).\n", read_bytes, sizeof(size_t)); return -1; } @@ -296,7 +332,7 @@ ssize_t read_string(int fd, char *restrict str, size_t len) { 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); + LOGE("Failed to read string: Promised bytes doesn't exist (%zd != %zu).\n", read_bytes, str_len); return -1; } @@ -349,7 +385,7 @@ bool check_unix_socket(int fd, bool block) { int timeout = block ? -1 : 0; poll(&pfd, 1, timeout); - return (pfd.revents & !POLLIN) != 0 ? false : true; + return pfd.revents & ~POLLIN ? false : true; } /* INFO: Cannot use restrict here as execv does not have restrict */ diff --git a/zygiskd/src/utils.h b/zygiskd/src/utils.h index 8e37bfe..360d931 100644 --- a/zygiskd/src/utils.h +++ b/zygiskd/src/utils.h @@ -14,10 +14,16 @@ 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__); \ + __android_log_print(ANDROID_LOG_ERROR , lp_select("zygiskd32", "zygiskd64"), __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 write_func_def(type) \ + ssize_t write_## type(int fd, type val) + +#define read_func_def(type) \ + ssize_t read_## type(int fd, type *val) + bool switch_mount_namespace(pid_t pid); void get_property(const char *name, char *restrict output); @@ -30,9 +36,25 @@ int chcon(const char *path, const char *restrict context); int unix_listener_from_path(char *path); -ssize_t send_fd(int sockfd, int fd); +// ssize_t send_fd(int sockfd, int fd); -ssize_t recv_fd(int sockfd, int *restrict fd); +// int recv_fd(int sockfd); + +ssize_t gwrite_fd(int fd, int sendfd); + +int gread_fd(int fd); + +write_func_def(int); +read_func_def(int); + +write_func_def(size_t); +read_func_def(size_t); + +write_func_def(uint32_t); +read_func_def(uint32_t); + +write_func_def(uint8_t); +read_func_def(uint8_t); ssize_t write_string(int fd, const char *restrict str); diff --git a/zygiskd/src/zygiskd.c b/zygiskd/src/zygiskd.c index 38e5525..31e35af 100644 --- a/zygiskd/src/zygiskd.c +++ b/zygiskd/src/zygiskd.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -173,26 +174,10 @@ static void load_modules(enum Architecture arch, struct Context *restrict contex 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; - } + case ARM64: { strcpy(arch_str, "arm64-v8a"); break; } + case X86_64: { strcpy(arch_str, "x86_64"); break; } + case ARM32: { strcpy(arch_str, "armeabi-v7a"); break; } + case X86: { strcpy(arch_str, "x86"); break; } } LOGI("Loading modules for architecture: %s\n", arch_str); @@ -258,7 +243,9 @@ static int create_daemon_socket(void) { return unix_listener_from_path(PATH_CP_NAME); } -static int spawn_companion(char *restrict name, int lib_fd) { +static int spawn_companion(char *restrict argv[], char *restrict name, int lib_fd) { + LOGI("Spawning a new companion...\n"); + int sockets[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { LOGE("Failed creating socket pair.\n"); @@ -269,11 +256,7 @@ static int spawn_companion(char *restrict name, int lib_fd) { int daemon_fd = sockets[0]; int companion_fd = sockets[1]; - LOGI("Companion fd: %d\n", companion_fd); - LOGI("Daemon fd: %d\n", daemon_fd); - pid_t pid = fork(); - LOGI("Forked: %d\n", pid); if (pid < 0) { LOGE("Failed forking companion: %s\n", strerror(errno)); @@ -284,66 +267,83 @@ static int spawn_companion(char *restrict name, int lib_fd) { } else if (pid > 0) { close(companion_fd); - LOGI("Waiting for companion to start (%d)\n", pid); - int 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) { - LOGE("Failed sending module name\n"); + LOGE("Failed writing module name.\n"); + + close(daemon_fd); return -1; } - if (send_fd(daemon_fd, lib_fd) == -1) { - LOGE("Failed sending lib fd\n"); + if (gwrite_fd(daemon_fd, lib_fd) == -1) { + LOGE("Failed sending library fd.\n"); + + close(daemon_fd); 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)); - - LOGI("Companion response: %hhu\n", response_buf[0]); - - if (response_buf[0] == 0) { - close(daemon_fd); - - return -1; - } else if (response_buf[0] == 1) return daemon_fd; - else { - LOGE("Invalid response from companion: %hhu\n", response_buf[0]); + uint8_t response = 0; + ssize_t ret = read_uint8_t(daemon_fd, &response); + if (ret <= 0) { + LOGE("Failed reading companion response.\n"); close(daemon_fd); return -1; } + + LOGI("Companion response: %hhu\n", response); + + switch (response) { + /* INFO: Even without any entry, we should still just deal with it */ + case 0: { return -2; } + case 1: { return daemon_fd; } + /* TODO: Should we be closing daemon socket here? (in non-0-and-1 case) */ + default: { + return -1; + } + } + /* TODO: Should we be closing daemon socket here? */ } else { LOGE("Exited with status %d\n", status); - close(daemon_fd); - return -1; } /* INFO: if pid == 0: */ } else { - LOGI("Companion started\n"); /* INFO: There is no case where this will fail with a valid fd. */ - fcntl(companion_fd, F_SETFD, 0); + /* INFO: Remove FD_CLOEXEC flag to avoid closing upon exec */ + if (fcntl(companion_fd, F_SETFD, 0) == -1) { + LOGE("Failed removing FD_CLOEXEC flag: %s\n", strerror(errno)); + + close(companion_fd); + close(daemon_fd); + + exit(1); + } } + char *process = argv[0]; + char nice_name[256]; + char *last = strrchr(process, '/'); + if (last == NULL) { + snprintf(nice_name, sizeof(nice_name), "%s", process); + } else { + snprintf(nice_name, sizeof(nice_name), "%s", last + 1); + } + + char process_name[256]; + snprintf(process_name, sizeof(process_name), "%s-%s", nice_name, name); + char companion_fd_str[32]; - snprintf(companion_fd_str, 32, "%d", companion_fd); + snprintf(companion_fd_str, sizeof(companion_fd_str), "%d", companion_fd); - LOGI("Executing companion...\n"); - - char *argv[] = { ZYGISKD_FILE, "companion", companion_fd_str, NULL }; - if (non_blocking_execv(ZYGISKD_PATH, argv) == -1) { + char *eargv[] = { process_name, "companion", companion_fd_str, NULL }; + if (non_blocking_execv(ZYGISKD_PATH, eargv) == -1) { LOGE("Failed executing companion: %s\n", strerror(errno)); close(companion_fd); @@ -351,8 +351,6 @@ static int spawn_companion(char *restrict name, int lib_fd) { exit(1); } - LOGI("Bye bye!\n"); - exit(0); } @@ -362,7 +360,7 @@ struct __attribute__((__packed__)) MsgHead { char data[0]; }; -void zygiskd_start(void) { +void zygiskd_start(char *restrict argv[]) { LOGI("Welcome to ReZygisk %s!\n", ZKSU_VERSION); enum RootImpl impl = get_impl(); @@ -517,10 +515,8 @@ void zygiskd_start(void) { return; } - LOGI("Accepted client: %d\n", client_fd); - - uint8_t buf[1]; - ssize_t len = read(client_fd, buf, sizeof(buf)); + uint8_t action8 = 0; + ssize_t len = read_uint8_t(client_fd, &action8); if (len == -1) { LOGE("read: %s\n", strerror(errno)); @@ -531,17 +527,22 @@ void zygiskd_start(void) { return; } - LOGI("Action: %hhu\n", buf[0]); - enum DaemonSocketAction action = (enum DaemonSocketAction)buf[0]; + enum DaemonSocketAction action = (enum DaemonSocketAction)action8; switch (action) { case PingHeartbeat: { + LOGI("ZD-- PingHeartbeat\n"); + enum DaemonSocketAction msgr = ZYGOTE_INJECTED; unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + LOGI("ZD++ PingHeartbeat\n"); + break; } case ZygoteRestart: { + LOGI("ZD-- ZygoteRestart\n"); + for (int i = 0; i < context.len; i++) { if (context.modules[i].companion != -1) { close(context.modules[i].companion); @@ -549,36 +550,40 @@ void zygiskd_start(void) { } } + LOGI("ZD++ ZygoteRestart\n"); + break; } case SystemServerStarted: { + LOGI("ZD-- SystemServerStarted\n"); + enum DaemonSocketAction msgr = SYSTEM_SERVER_STARTED; unix_datagram_sendto(CONTROLLER_SOCKET, &msgr, sizeof(enum DaemonSocketAction)); + LOGI("ZD++ SystemServerStarted\n"); + break; } - /* TODO: May need to move to another thread? :/ */ case RequestLogcatFd: { - 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)); - - uint8_t level = level_buf[0]; + uint8_t level = 0; + ssize_t ret = read_uint8_t(client_fd, &level); + ASSURE_SIZE_READ_BREAK("RequestLogcatFd", "level", ret, sizeof(level)); char tag[128 + 1]; ret = read_string(client_fd, tag, sizeof(tag) - 1); if (ret == -1) { - LOGE("Failed reading tag\n"); + LOGE("Failed reading logcat tag.\n"); break; } tag[ret] = '\0'; + /* INFO: Non-NULL terminated */ char message[1024]; ret = read_string(client_fd, message, sizeof(message)); if (ret == -1) { - LOGE("Failed reading message\n"); + LOGE("Failed reading logcat message.\n"); break; } @@ -588,13 +593,11 @@ void zygiskd_start(void) { break; } case GetProcessFlags: { - LOGI("Getting process flags\n"); + LOGI("ZD-- GetProcessFlags\n"); - 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)); - - uint32_t uid = uid_buf[0]; + uint32_t uid = 0; + ssize_t ret = read_uint32_t(client_fd, &uid); + ASSURE_SIZE_READ_BREAK("GetProcessFlags", "uid", ret, sizeof(uid)); uint32_t flags = 0; if (uid_is_manager(uid)) { @@ -608,8 +611,6 @@ void zygiskd_start(void) { } } - LOGI("Flags for uid %d: %d\n", uid, flags); - switch (get_impl()) { case None: { break; } case Multiple: { break; } @@ -630,17 +631,17 @@ void zygiskd_start(void) { } } - ret = write(client_fd, &flags, sizeof(flags)); + ret = write_int(client_fd, flags); ASSURE_SIZE_WRITE_BREAK("GetProcessFlags", "flags", ret, sizeof(flags)); - LOGI("Sent flags\n"); + LOGI("ZD++ GetProcessFlags\n"); break; } case GetInfo: { - uint32_t flags = 0; + LOGI("ZD-- GetInfo\n"); - LOGI("Getting info\n"); + uint32_t flags = 0; switch (get_impl()) { case None: { break; } @@ -662,72 +663,52 @@ void zygiskd_start(void) { } } - LOGI("Flags: %d\n", flags); - - ssize_t ret = write(client_fd, &flags, sizeof(flags)); + ssize_t ret = write_size_t(client_fd, flags); ASSURE_SIZE_WRITE_BREAK("GetInfo", "flags", ret, sizeof(flags)); - uint32_t pid = getpid(); - - LOGI("Getting pid: %d\n", pid); - - ret = write(client_fd, &pid, sizeof(pid)); + uint32_t pid = getpid(); + ret = write_uint32_t(client_fd, pid); ASSURE_SIZE_WRITE_BREAK("GetInfo", "pid", ret, sizeof(pid)); - LOGI("Sent pid\n"); - size_t modules_len = context.len; - ret = write(client_fd, &modules_len, sizeof(modules_len)); + ret = write_size_t(client_fd, modules_len); for (size_t i = 0; i < modules_len; i++) { write_string(client_fd, context.modules[i].name); } + LOGI("ZD++ GetInfo\n"); + break; } case ReadModules: { - LOGI("Reading modules to stream\n"); + LOGI("ZD-- ReadModules\n"); size_t clen = context.len; - ssize_t ret = write(client_fd, &clen, sizeof(clen)); + ssize_t ret = write_size_t(client_fd, clen); ASSURE_SIZE_WRITE_BREAK("ReadModules", "len", ret, sizeof(clen)); 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); - - if (write_string(client_fd, context.modules[i].name) == -1) { - LOGE("Failed writing module name\n"); - - break; - } - - if (send_fd(client_fd, context.modules[i].lib_fd) == -1) { - LOGE("Failed sending lib fd\n"); - - break; - } + if (write_string(client_fd, context.modules[i].name) == -1) break; + if (gwrite_fd(client_fd, context.modules[i].lib_fd) == -1) break; } - LOGI("Finished reading modules to stream\n"); + LOGI("ZD++ ReadModules\n"); break; } case RequestCompanionSocket: { - LOGI("Requesting companion socket\n"); - - 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("ZD-- RequestCompanionSocket\n"); - size_t index = index_buf[0]; + size_t index = 0; + ssize_t ret = read_size_t(client_fd, &index); + ASSURE_SIZE_READ_BREAK("RequestCompanionSocket", "index", ret, sizeof(index)); struct Module *module = &context.modules[index]; if (module->companion != -1) { - LOGI("Companion for module `%s` already exists\n", module->name); - if (!check_unix_socket(module->companion, false)) { - LOGE("Poll companion for module `%s` crashed\n", module->name); + LOGE(" Poll companion for module \"%s\" crashed\n", module->name); close(module->companion); module->companion = -1; @@ -735,74 +716,74 @@ void zygiskd_start(void) { } if (module->companion == -1) { - LOGI("Spawning companion for `%s`\n", module->name); + module->companion = spawn_companion(argv, module->name, module->lib_fd); - module->companion = spawn_companion(module->name, module->lib_fd); - - if (module->companion != -1) { - LOGI("Spawned companion for `%s`\n", module->name); - - /* INFO: Reversed params, may fix issues */ - if (send_fd(module->companion, client_fd) == -1) { - LOGE("Failed sending companion fd\n"); - - uint8_t response = 0; - ret = write(client_fd, &response, sizeof(response)); - ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(response)); - } + if (module->companion > 0) { + LOGI(" Spawned companion for \"%s\"\n", module->name); } else { if (module->companion == -2) { - LOGI("Could not spawn companion for `%s` as it has no entry\n", module->name); + LOGE(" No companion spawned for \"%s\" because it has no entry.\n", module->name); } else { - LOGI("Could not spawn companion for `%s` due to failures.\n", module->name); + LOGE(" Failed to spawn companion for \"%s\": %s\n", module->name, strerror(errno)); } } - - 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", module->companion); } + if (module->companion != -1) { + if (gwrite_fd(module->companion, client_fd) == -1) { + LOGE("Failed to send companion fd socket of module \"%s\"\n", module->name); + + ret = write_int(client_fd, 0); + ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(int)); + } + } else { + ret = write_int(client_fd, 0); + ASSURE_SIZE_WRITE_BREAK("RequestCompanionSocket", "response", ret, sizeof(int)); + } + + LOGI("ZD++ RequestCompanionSocket\n"); + break; } case GetModuleDir: { - LOGI("Getting module directory\n"); + LOGI("ZD-- GetModuleDir\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 = 0; + read_size_t(client_fd, &index); - size_t index = index_buf[0]; + char module_dir[PATH_MAX]; + snprintf(module_dir, PATH_MAX, "%s/%s", PATH_MODULES_DIR, context.modules[index].name); - 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); - /* 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) { - LOGE("Failed sending module directory fd\n"); - - close(dir_fd); + int fd = open(module_dir, O_RDONLY); + if (fd == -1) { + LOGE("Failed opening module directory \"%s\": %s\n", module_dir, strerror(errno)); break; } - LOGI("Sent module directory fd\n"); + struct stat st; + if (fstat(fd, &st) == -1) { + LOGE("Failed getting module directory \"%s\" stats: %s\n", module_dir, strerror(errno)); + + close(fd); + + break; + } + + if (gwrite_fd(client_fd, fd) == -1) { + LOGE("Failed sending module directory \"%s\" fd: %s\n", module_dir, strerror(errno)); + + close(fd); + + break; + } + + LOGI("ZD++ GetModuleDir\n"); break; } } - close(client_fd); - continue; } diff --git a/zygiskd/src/zygiskd.h b/zygiskd/src/zygiskd.h index 9492a50..868556a 100644 --- a/zygiskd/src/zygiskd.h +++ b/zygiskd/src/zygiskd.h @@ -1,6 +1,6 @@ #ifndef ZYGISKD_H #define ZYGISKD_H -void zygiskd_start(void); +void zygiskd_start(char *restrict argv[]); #endif /* ZYGISKD_H */