diff --git a/loader/src/common/daemon.cpp b/loader/src/common/daemon.cpp index 5649f006..bd558caf 100644 --- a/loader/src/common/daemon.cpp +++ b/loader/src/common/daemon.cpp @@ -63,19 +63,6 @@ namespace zygiskd { 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) { diff --git a/loader/src/common/logging.cpp b/loader/src/common/logging.cpp deleted file mode 100644 index 887025f8..00000000 --- a/loader/src/common/logging.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "logging.h" -#include "socket_utils.h" - -namespace logging { - static int logfd = -1; - - void setfd(int fd) { - close(logfd); - logfd = fd; - } - - int getfd() { - return logfd; - } - - void log(int prio, const char* tag, const char* fmt, ...) { - if (logfd == -1) { - va_list ap; - va_start(ap, fmt); - __android_log_vprint(prio, tag, fmt, ap); - va_end(ap); - } else { - char buf[BUFSIZ]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - socket_utils::write_u8(logfd, prio); - socket_utils::write_string(logfd, tag); - socket_utils::write_string(logfd, buf); - } - } -} diff --git a/loader/src/include/daemon.h b/loader/src/include/daemon.h index 7016ca97..dad3c18f 100644 --- a/loader/src/include/daemon.h +++ b/loader/src/include/daemon.h @@ -78,7 +78,6 @@ namespace zygiskd { enum class SocketAction { PingHeartBeat, - RequestLogcatFd, GetProcessFlags, GetInfo, ReadModules, @@ -95,8 +94,6 @@ namespace zygiskd { bool PingHeartbeat(); - int RequestLogcatFd(); - std::vector ReadModules(); uint32_t GetProcessFlags(uid_t uid); diff --git a/loader/src/include/logging.h b/loader/src/include/logging.h index 0318bbe1..687fdaf8 100644 --- a/loader/src/include/logging.h +++ b/loader/src/include/logging.h @@ -1,35 +1,30 @@ -#pragma once +#ifndef LOGGING_H +#define LOGGING_H #include #include #include #ifndef LOG_TAG -#if defined(__LP64__) -# define LOG_TAG "zygisk-core64" -#else -# define LOG_TAG "zygisk-core32" -#endif + #ifdef __LP64__ + #define LOG_TAG "zygisk-core64" + #else + #define LOG_TAG "zygisk-core32" + #endif #endif #ifndef NDEBUG -#define LOGD(...) logging::log(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#define LOGV(...) logging::log(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) + #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) + #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) #else -#define LOGD(...) -#define LOGV(...) + #define LOGD(...) + #define LOGV(...) #endif -#define LOGI(...) logging::log(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define LOGW(...) logging::log(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define LOGE(...) logging::log(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#define LOGF(...) logging::log(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__) -#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)) -namespace logging { - void setfd(int fd); - - int getfd(); +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__) +#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)) - [[gnu::format(printf, 3, 4)]] - void log(int prio, const char* tag, const char* fmt, ...); -} +#endif /* LOGGING_H */ \ No newline at end of file diff --git a/loader/src/injector/entry.cpp b/loader/src/injector/entry.cpp index 773475dd..fabe2097 100644 --- a/loader/src/injector/entry.cpp +++ b/loader/src/injector/entry.cpp @@ -19,10 +19,6 @@ void entry(void* addr, size_t size, const char* path) { return; } -#ifdef NDEBUG - logging::setfd(zygiskd::RequestLogcatFd()); -#endif - LOGD("start plt hooking"); hook_functions(); clean_trace(path, 1, 0, false); diff --git a/loader/src/injector/hook.cpp b/loader/src/injector/hook.cpp index cf5f0128..14c5fa3d 100644 --- a/loader/src/injector/hook.cpp +++ b/loader/src/injector/hook.cpp @@ -175,8 +175,10 @@ DCL_HOOK_FUNC(int, unshare, int flags) { // This is reproducible on the official AVD running API 26 and 27. // Simply avoid doing any unmounts for SysUI to avoid potential issues. !g_ctx->flags[SERVER_FORK_AND_SPECIALIZE] && !(g_ctx->info_flags & PROCESS_IS_FIRST_STARTED)) { - if (g_ctx->flags[DO_REVERT_UNMOUNT]) { - update_mnt_ns(Clean, false); + if (g_ctx->info_flags & (PROCESS_IS_MANAGER | PROCESS_GRANTED_ROOT)) { + update_mnt_ns(Rooted, false); + } else if (!(g_ctx->flags[DO_REVERT_UNMOUNT])) { + update_mnt_ns(Module, false); } old_unshare(CLONE_NEWNS); @@ -188,18 +190,6 @@ DCL_HOOK_FUNC(int, unshare, int flags) { return res; } -// Close logd_fd if necessary to prevent crashing -// For more info, check comments in zygisk_log_write -DCL_HOOK_FUNC(void, android_log_close) { - if (g_ctx == nullptr) { - // Happens during un-managed fork like nativeForkApp, nativeForkUsap - logging::setfd(-1); - } else if (!g_ctx->flags[SKIP_FD_SANITIZATION]) { - logging::setfd(-1); - } - old_android_log_close(); -} - // We cannot directly call `dlclose` to unload ourselves, otherwise when `dlclose` returns, // it will return to our code which has been unmapped, causing segmentation fault. // Instead, we hook `pthread_attr_setstacksize` which will be called when VM daemon threads start. @@ -628,6 +618,10 @@ void ZygiskContext::app_specialize_pre() { flags[APP_SPECIALIZE] = true; info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid); + if (info_flags & PROCESS_IS_FIRST_STARTED) { + update_mnt_ns(Clean, true); + } + if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) { flags[DO_REVERT_UNMOUNT] = true; } @@ -648,7 +642,6 @@ void ZygiskContext::app_specialize_post() { // Cleanups env->ReleaseStringUTFChars(args.app->nice_name, process); g_ctx = nullptr; - logging::setfd(-1); } bool ZygiskContext::exempt_fd(int fd) { @@ -681,11 +674,10 @@ void ZygiskContext::nativeForkSystemServer_pre() { flags[SERVER_FORK_AND_SPECIALIZE] = true; fork_pre(); - if (pid != 0) - return; - - run_modules_pre(); - zygiskd::SystemServerStarted(); + if (is_child()) { + run_modules_pre(); + zygiskd::SystemServerStarted(); + } sanitize_fds(); } @@ -703,10 +695,7 @@ void ZygiskContext::nativeForkAndSpecialize_pre() { LOGV("pre forkAndSpecialize [%s]", process); flags[APP_FORK_AND_SPECIALIZE] = true; - /* Zygisksu changed: No args.app->fds_to_ignore check since we are Android 10+ */ - if (logging::getfd() != -1) { - exempted_fds.push_back(logging::getfd()); - } + update_mnt_ns(Clean, false); fork_pre(); if (pid == 0) { @@ -831,7 +820,6 @@ void hook_functions() { PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork); PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare); PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, strdup); - PLT_HOOK_REGISTER_SYM(android_runtime_dev, android_runtime_inode, "__android_log_close", android_log_close); hook_commit(); // Remove unhooked methods diff --git a/loader/src/injector/module.hpp b/loader/src/injector/module.hpp index ae8d4103..f02bd7d2 100644 --- a/loader/src/injector/module.hpp +++ b/loader/src/injector/module.hpp @@ -126,8 +126,8 @@ namespace { PROCESS_GRANTED_ROOT = zygisk::StateFlag::PROCESS_GRANTED_ROOT, PROCESS_ON_DENYLIST = zygisk::StateFlag::PROCESS_ON_DENYLIST, - PROCESS_IS_MANAGER = (1u << 28), - PROCESS_ROOT_IS_APATCH = (1u << 27), + PROCESS_IS_MANAGER = (1u << 27), + PROCESS_ROOT_IS_APATCH = (1u << 28), PROCESS_ROOT_IS_KSU = (1u << 29), PROCESS_ROOT_IS_MAGISK = (1u << 30), PROCESS_IS_FIRST_STARTED = (1u << 31), diff --git a/zygiskd/build.gradle.kts b/zygiskd/build.gradle.kts index b8301890..a3a2984a 100644 --- a/zygiskd/build.gradle.kts +++ b/zygiskd/build.gradle.kts @@ -42,7 +42,7 @@ val CFlagsRelease = arrayOf( ) val CFlagsDebug = arrayOf( - "-g", "-O0" + "-g", "-O0", "-DDEBUG" ) val Files = arrayOf( diff --git a/zygiskd/src/constants.h b/zygiskd/src/constants.h index 55d482f2..71e3f29e 100644 --- a/zygiskd/src/constants.h +++ b/zygiskd/src/constants.h @@ -7,12 +7,6 @@ #define true 1 #define false 0 -#if DEBUG == false - #define MAX_LOG_LEVEL ANDROID_LOG_VERBOSE -#else - #define MAX_LOG_LEVEL ANDROID_LOG_INFO -#endif - #if (defined(__LP64__) || defined(_LP64)) #define lp_select(a, b) b #else @@ -26,22 +20,21 @@ enum DaemonSocketAction { PingHeartbeat = 0, - RequestLogcatFd = 1, - GetProcessFlags = 2, - GetInfo = 3, - ReadModules = 4, - RequestCompanionSocket = 5, - GetModuleDir = 6, - ZygoteRestart = 7, - SystemServerStarted = 8, - GetCleanNamespace = 9 + GetProcessFlags = 1, + GetInfo = 2, + ReadModules = 3, + RequestCompanionSocket = 4, + GetModuleDir = 5, + ZygoteRestart = 6, + SystemServerStarted = 7, + GetCleanNamespace = 8 }; 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_IS_MANAGER = (1u << 27), + PROCESS_ROOT_IS_APATCH = (1u << 28), PROCESS_ROOT_IS_KSU = (1u << 29), PROCESS_ROOT_IS_MAGISK = (1u << 30), PROCESS_IS_FIRST_STARTED = (1u << 31) diff --git a/zygiskd/src/utils.c b/zygiskd/src/utils.c index 381b61b9..69225996 100644 --- a/zygiskd/src/utils.c +++ b/zygiskd/src/utils.c @@ -626,41 +626,63 @@ enum mns_umount_state unmount_root(bool modules_only, struct root_impl impl) { char source_name[LONGEST_ROOT_IMPL_NAME]; if (impl.impl == KernelSU) strcpy(source_name, "KSU"); else strcpy(source_name, "APatch"); + + const char **targets_to_unmount = NULL; + size_t num_targets = 0; - for (size_t i = mounts.length - 1; i > 0; i--) { + for (size_t i = 0; i < mounts.length; i++) { struct mountinfo mount = mounts.mounts[i]; - if ( - ( - modules_only && - ( - strncmp(mount.target, "/debug_ramdisk", strlen("/debug_ramdisk")) == 0 - ) - ) || - ( - strcmp(mount.source, source_name) == 0 || - strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0 || - strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0 - ) - ) { - if (umount2(mount.target, MNT_DETACH) == -1) { - LOGE("[Magisk] Failed to unmount %s: %s\n", mount.target, strerror(errno)); + bool should_unmount = false; + + if (modules_only) { + if (strncmp(mount.target, "/debug_ramdisk", strlen("/debug_ramdisk")) == 0) + should_unmount = true; + } else { + if (strcmp(mount.source, source_name) == 0) should_unmount = true; + if (strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) should_unmount = true; + if (strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0) should_unmount = true; + } + + if (!should_unmount) continue; + + num_targets++; + targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*)); + if (targets_to_unmount == NULL) { + LOGE("[%s] Failed to allocate memory for targets_to_unmount\n", source_name); + + free(targets_to_unmount); + free_mounts(&mounts); + + return Error; + } + + targets_to_unmount[num_targets - 1] = mount.target; + } - continue; - } + for (size_t i = num_targets; i > 0; i--) { + const char *target = targets_to_unmount[i - 1]; - LOGI("[%s] Unmounted %s (%s | %s)\n", source_name, mount.target, mount.root, mount.source); + if (umount2(target, MNT_DETACH) == -1) { + LOGE("[%s] Failed to unmount %s: %s\n", source_name, target, strerror(errno)); + } else { + LOGI("[%s] Unmounted %s\n", source_name, target); } } + free(targets_to_unmount); break; } case Magisk: { LOGI("[Magisk] Unmounting root %s modules\n", modules_only ? "only" : "with"); + + const char **targets_to_unmount = NULL; + size_t num_targets = 0; - for (size_t i = mounts.length - 1; i > 0; i--) { + for (size_t i = 0; i < mounts.length; i++) { struct mountinfo mount = mounts.mounts[i]; + bool should_unmount = false; if ( ( modules_only && @@ -681,20 +703,39 @@ enum mns_umount_state unmount_root(bool modules_only, struct root_impl impl) { ) ) ) { - if (impl.impl == Magisk && strncmp(mount.target, "/system/bin", strlen("/system/bin")) == 0) - magiskSU_umounted = true; + should_unmount = true; + } + + if (!should_unmount) continue; + + num_targets++; + targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*)); + if (targets_to_unmount == NULL) { + LOGE("[Magisk] Failed to allocate memory for targets_to_unmount\n"); + + free(targets_to_unmount); + free_mounts(&mounts); - if (umount2(mount.target, MNT_DETACH) == -1) { - LOGE("[Magisk] Failed to unmount %s: %s\n", mount.target, strerror(errno)); + return Error; + } + + targets_to_unmount[num_targets - 1] = mount.target; - continue; - } + if (impl.impl == Magisk && strncmp(mount.target, "/system/bin", strlen("/system/bin")) == 0) + magiskSU_umounted = true; + } - LOGI("[Magisk] Unmounted %s\n", mount.target); + for (size_t i = num_targets; i > 0; i--) { + const char *target = targets_to_unmount[i - 1]; + if (umount2(target, MNT_DETACH) == -1) { + LOGE("[Magisk] Failed to unmount %s: %s\n", target, strerror(errno)); } else { - LOGI("[Magisk] Skipped unmounting %s (%s | %s)\n", mount.target, mount.root, mount.source); + LOGI("[Magisk] Unmounted %s\n", target); } } + free(targets_to_unmount); + + break; } } @@ -704,12 +745,6 @@ enum mns_umount_state unmount_root(bool modules_only, struct root_impl impl) { } int save_mns_fd(int pid, enum MountNamespaceState mns_state, struct root_impl impl) { - LOGI(" - Saving mount namespace fd for pid %d. State: %d\n", pid, mns_state); - - LOGI(" - Clean namespace fd: %d\n", clean_namespace_fd); - LOGI(" - Rooted namespace fd: %d\n", rooted_namespace_fd); - LOGI(" - Module namespace fd: %d\n", module_namespace_fd); - if (mns_state == Clean && clean_namespace_fd != 0) return clean_namespace_fd; if (mns_state == Rooted && rooted_namespace_fd != 0) return rooted_namespace_fd; if (mns_state == Module && module_namespace_fd != 0) return module_namespace_fd; @@ -788,8 +823,6 @@ int save_mns_fd(int pid, enum MountNamespaceState mns_state, struct root_impl im return -1; } - LOGI(" - Forked child exited\n"); - if (mns_state == Rooted) return (rooted_namespace_fd = ns_fd); else if (mns_state == Clean && umount_state == Complete) return (clean_namespace_fd = ns_fd); else if (mns_state == Module && umount_state == Complete) return (module_namespace_fd = ns_fd); diff --git a/zygiskd/src/zygiskd.c b/zygiskd/src/zygiskd.c index 2b813f2f..9b0546bd 100644 --- a/zygiskd/src/zygiskd.c +++ b/zygiskd/src/zygiskd.c @@ -47,8 +47,6 @@ enum Architecture { #define ZYGISKD_FILE PATH_MODULES_DIR "/zygisksu/bin/zygiskd" lp_select("32", "64") #define ZYGISKD_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64") -bool first_process = true; - static enum Architecture get_arch(void) { char system_arch[32]; get_property("ro.product.cpu.abi", system_arch); @@ -412,6 +410,7 @@ void zygiskd_start(char *restrict argv[]) { return; } + bool first_process = true; while (1) { int client_fd = accept(socket_fd, NULL, NULL); if (client_fd == -1) { @@ -467,37 +466,6 @@ void zygiskd_start(char *restrict argv[]) { break; } - /* TODO: Move to another thread and save client fds to an epoll list - so that we can, in a single-thread, deal with multiple logcats */ - case RequestLogcatFd: { - 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)); - if (ret == -1) { - LOGE("Failed reading logcat tag.\n"); - - close(client_fd); - - break; - } - - char message[1024 + 1]; - ret = read_string(client_fd, message, sizeof(message)); - if (ret == -1) { - LOGE("Failed reading logcat message.\n"); - - close(client_fd); - - break; - } - - __android_log_print(level, tag, "%s", message); - - break; - } case GetProcessFlags: { uint32_t uid = 0; ssize_t ret = read_uint32_t(client_fd, &uid); @@ -718,10 +686,15 @@ void zygiskd_start(char *restrict argv[]) { ret = read_uint8_t(client_fd, &mns_state); ASSURE_SIZE_READ_BREAK("GetCleanNamespace", "mns_state", ret, sizeof(mns_state)); - pid_t our_pid = getpid(); + uint32_t our_pid = (uint32_t)getpid(); ret = write_uint32_t(client_fd, (uint32_t)our_pid); ASSURE_SIZE_WRITE_BREAK("GetCleanNamespace", "our_pid", ret, sizeof(our_pid)); + if ((enum MountNamespaceState)mns_state == Clean) { + save_mns_fd(pid, Rooted, impl); + save_mns_fd(pid, Module, impl); + } + uint32_t clean_namespace_fd = (uint32_t)save_mns_fd(pid, (enum MountNamespaceState)mns_state, impl); ret = write_uint32_t(client_fd, clean_namespace_fd); ASSURE_SIZE_WRITE_BREAK("GetCleanNamespace", "clean_namespace_fd", ret, sizeof(clean_namespace_fd)); @@ -730,7 +703,7 @@ void zygiskd_start(char *restrict argv[]) { } } - if (action != RequestCompanionSocket && action != RequestLogcatFd) close(client_fd); + if (action != RequestCompanionSocket) close(client_fd); continue; }