From decdd54c19345137a088e4c23496af3f268eb549 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 19 Aug 2021 04:55:17 -0700 Subject: [PATCH] Hook up denylist IPC routines --- native/jni/magiskhide/hide_policy.cpp | 7 ++-- native/jni/magiskhide/magiskhide.hpp | 2 +- native/jni/zygisk/entry.cpp | 57 +++++++++++++++++++++++++++ native/jni/zygisk/hook.cpp | 13 ++---- native/jni/zygisk/inject.hpp | 4 ++ 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/native/jni/magiskhide/hide_policy.cpp b/native/jni/magiskhide/hide_policy.cpp index 85e8e07e5..19d316fd8 100644 --- a/native/jni/magiskhide/hide_policy.cpp +++ b/native/jni/magiskhide/hide_policy.cpp @@ -14,11 +14,10 @@ static void lazy_unmount(const char* mountpoint) { LOGD("hide: Unmounted (%s)\n", mountpoint); } -void hide_daemon(int pid) { +void hide_daemon(int pid, int client) { if (fork_dont_care() == 0) { hide_unmount(pid); - // Send resume signal - kill(pid, SIGCONT); + write_int(client, 0); _exit(0); } } @@ -29,7 +28,7 @@ void hide_unmount(int pid) { if (pid > 0 && switch_mnt_ns(pid)) return; - LOGD("hide: handling PID=[%d]\n", pid); + LOGD("hide: handling PID=[%d]\n", pid > 0 ? pid : getpid()); vector targets; diff --git a/native/jni/magiskhide/magiskhide.hpp b/native/jni/magiskhide/magiskhide.hpp index 12ffa7dc6..5796c7b74 100644 --- a/native/jni/magiskhide/magiskhide.hpp +++ b/native/jni/magiskhide/magiskhide.hpp @@ -21,7 +21,7 @@ bool hide_enabled(); bool is_hide_target(int uid, std::string_view process); // Hide policies -void hide_daemon(int pid); +void hide_daemon(int pid, int client); void hide_unmount(int pid = -1); enum { diff --git a/native/jni/zygisk/entry.cpp b/native/jni/zygisk/entry.cpp index 16d1a7d03..d317e5951 100644 --- a/native/jni/zygisk/entry.cpp +++ b/native/jni/zygisk/entry.cpp @@ -9,6 +9,7 @@ #include #include "inject.hpp" +#include "../magiskhide/magiskhide.hpp" using namespace std; @@ -124,6 +125,8 @@ static void inject_init() { } } +// Start code for magiskd IPC + int app_process_main(int argc, char *argv[]) { android_logging(); @@ -154,6 +157,34 @@ int app_process_main(int argc, char *argv[]) { return 1; } +bool remote_check_denylist(int uid, const char *process) { + if (int fd = connect_daemon(); fd >= 0) { + write_int(fd, ZYGISK_REQUEST); + write_int(fd, ZYGISK_CHECK_DENYLIST); + + int ret = -1; + if (read_int(fd) == 0) { + write_int(fd, uid); + write_string(fd, process); + ret = read_int(fd); + } + close(fd); + return ret >= 0 && ret; + } + return false; +} + +int remote_request_unmount() { + if (int fd = connect_daemon(); fd >= 0) { + write_int(fd, ZYGISK_REQUEST); + write_int(fd, ZYGISK_UNMOUNT); + int ret = read_int(fd); + close(fd); + return ret; + } + return DAEMON_ERROR; +} + // The following code runs in magiskd static void setup_files(int client, ucred *cred) { @@ -175,12 +206,38 @@ static void setup_files(int client, ucred *cred) { write_string(client, path); } +static void check_denylist(int client) { + if (!hide_enabled()) { + write_int(client, HIDE_NOT_ENABLED); + return; + } + write_int(client, 0); + int uid = read_int(client); + string process = read_string(client); + write_int(client, is_hide_target(uid, process)); +} + +static void do_unmount(int client, ucred *cred) { + LOGD("zygisk: cleanup mount namespace for pid=[%d]\n", cred->pid); + if (hide_enabled()) { + hide_daemon(cred->pid, client); + } else { + write_int(client, HIDE_NOT_ENABLED); + } +} + void zygisk_handler(int client, ucred *cred) { int code = read_int(client); switch (code) { case ZYGISK_SETUP: setup_files(client, cred); break; + case ZYGISK_CHECK_DENYLIST: + check_denylist(client); + break; + case ZYGISK_UNMOUNT: + do_unmount(client, cred); + break; } close(client); } diff --git a/native/jni/zygisk/hook.cpp b/native/jni/zygisk/hook.cpp index fff415f7b..c63f8ec51 100644 --- a/native/jni/zygisk/hook.cpp +++ b/native/jni/zygisk/hook.cpp @@ -129,12 +129,6 @@ string get_class_name(JNIEnv *env, jclass clazz) { // ----------------------------------------------------------------- -// TODO -int remote_check_denylist(int uid, const char *process) { return 0; } -void remote_request_unmount() {} - -// ----------------------------------------------------------------- - #define DCL_HOOK_FUNC(ret, func, ...) \ ret (*old_##func)(__VA_ARGS__); \ ret new_##func(__VA_ARGS__) @@ -161,10 +155,11 @@ DCL_HOOK_FUNC(int, fork) { DCL_HOOK_FUNC(int, selinux_android_setcontext, uid_t uid, int isSystemServer, const char *seinfo, const char *pkgname) { if (g_ctx && g_ctx->flags[DENY_FLAG]) { - // Ask magiskd to cleanup the mount namespace before switching context + // Ask magiskd to cleanup our mount namespace before switching context // This is the latest point where we can still connect to the magiskd main socket - remote_request_unmount(); - LOGD("zygisk: process successfully hidden\n"); + if (remote_request_unmount() == 0) { + LOGD("zygisk: mount namespace cleaned up\n"); + } } return old_selinux_android_setcontext(uid, isSystemServer, seinfo, pkgname); } diff --git a/native/jni/zygisk/inject.hpp b/native/jni/zygisk/inject.hpp index 82b923fc3..dd5e59f49 100644 --- a/native/jni/zygisk/inject.hpp +++ b/native/jni/zygisk/inject.hpp @@ -8,6 +8,8 @@ enum : int { ZYGISK_SETUP, + ZYGISK_CHECK_DENYLIST, + ZYGISK_UNMOUNT, }; // Unmap all pages matching the name @@ -22,3 +24,5 @@ uintptr_t get_function_addr(int pid, const char *lib, uintptr_t off); void self_unload(); void hook_functions(); bool unhook_functions(); +bool remote_check_denylist(int uid, const char *process); +int remote_request_unmount();