improve: mounting system, compatibility; remove: logging on release (#111)

This commit adds numerous improvements to the state of hidden'ility of ReZygisk, and also for compatibility. Recommended to check #111 for more information.
This commit is contained in:
Pedro.js
2025-03-29 12:17:57 -03:00
committed by GitHub
parent 9aafc279d5
commit 886e2f8396
20 changed files with 621 additions and 412 deletions

View File

@@ -137,6 +137,36 @@ DCL_HOOK_FUNC(int, fork) {
return (g_ctx && g_ctx->pid >= 0) ? g_ctx->pid : old_fork();
}
bool update_mnt_ns(enum mount_namespace_state mns_state, bool dry_run) {
std::string ns_path = zygiskd::UpdateMountNamespace(mns_state);
if (ns_path.empty()) {
PLOGE("Failed to update mount namespace");
return false;
}
if (dry_run) return true;
int updated_ns = open(ns_path.data(), O_RDONLY);
if (updated_ns == -1) {
PLOGE("Failed to open mount namespace [%s]", ns_path.data());
return false;
}
LOGD("set mount namespace to [%s] fd=[%d]\n", ns_path.data(), updated_ns);
if (setns(updated_ns, CLONE_NEWNS) == -1) {
PLOGE("Failed to set mount namespace [%s]", ns_path.data());
close(updated_ns);
return false;
}
close(updated_ns);
return true;
}
// Unmount stuffs in the process's private mount namespace
DCL_HOOK_FUNC(int, unshare, int flags) {
int res = old_unshare(flags);
@@ -144,37 +174,22 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
// For some unknown reason, unmounting app_process in SysUI can break.
// 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->info_flags & PROCESS_IS_SYS_UI) == 0) {
if (g_ctx->flags[DO_REVERT_UNMOUNT]) {
if (g_ctx->info_flags & PROCESS_ROOT_IS_KSU) {
revert_unmount_ksu();
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_APATCH){
revert_unmount_apatch();
} else if (g_ctx->info_flags & PROCESS_ROOT_IS_MAGISK) {
revert_unmount_magisk();
}
!g_ctx->flags[SERVER_FORK_AND_SPECIALIZE] && !(g_ctx->info_flags & PROCESS_IS_FIRST_STARTED)) {
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);
}
/* Zygisksu changed: No umount app_process */
// Restore errno back to 0
errno = 0;
old_unshare(CLONE_NEWNS);
}
/* INFO: To spoof the errno value */
errno = 0;
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.
@@ -189,11 +204,13 @@ DCL_HOOK_FUNC(int, pthread_attr_setstacksize, void *target, size_t size) {
if (should_unmap_zygisk) {
unhook_functions();
cached_map_infos.clear();
if (should_unmap_zygisk) {
// Because both `pthread_attr_setstacksize` and `dlclose` have the same function signature,
// we can use `musttail` to let the compiler reuse our stack frame and thus
// `dlclose` will directly return to the caller of `pthread_attr_setstacksize`.
LOGI("unmap libzygisk.so loaded at %p with size %zu", start_addr, block_size);
LOGD("unmap libzygisk.so loaded at %p with size %zu", start_addr, block_size);
[[clang::musttail]] return munmap(start_addr, block_size);
}
}
@@ -598,14 +615,18 @@ void ZygiskContext::run_modules_post() {
/* Zygisksu changed: Load module fds */
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;
flags[DO_REVERT_UNMOUNT] = true;
}
if ((info_flags & (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) == (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) {
LOGI("Manager process detected. Notifying that Zygisk has been enabled.");
LOGD("Manager process detected. Notifying that Zygisk has been enabled.");
setenv("ZYGISK_ENABLED", "1", 1);
} else {
@@ -620,7 +641,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) {
@@ -653,11 +673,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();
}
@@ -673,12 +692,9 @@ void ZygiskContext::nativeForkSystemServer_post() {
void ZygiskContext::nativeForkAndSpecialize_pre() {
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
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) {
@@ -805,7 +821,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