diff --git a/zygiskd/src/root_impl/kernelsu.c b/zygiskd/src/root_impl/kernelsu.c index a6894d8..f2f2d74 100644 --- a/zygiskd/src/root_impl/kernelsu.c +++ b/zygiskd/src/root_impl/kernelsu.c @@ -20,9 +20,13 @@ #define CMD_UID_GRANTED_ROOT 12 #define CMD_UID_SHOULD_UMOUNT 13 #define CMD_HOOK_MODE 16 +#define CMD_GET_MANAGER_UID 17 static enum kernelsu_variants variant = KOfficial; +static uid_t manager_uid = 0; +static bool supports_manager_uid_retrieval = false; + void ksu_get_existence(struct root_impl_state *state) { int version = 0; prctl((signed int)KERNEL_SU_OPTION, CMD_GET_VERSION, &version, 0, 0); @@ -53,6 +57,18 @@ void ksu_get_existence(struct root_impl_state *state) { else state->variant = KOfficial; variant = state->variant; + + /* INFO: CMD_GET_MANAGER_UID is a KernelSU Next feature, however we won't + limit to KernelSU Next only in case other forks wish to implement + it. */ + int reply_ok = 0; + prctl((signed int)KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, 0, 0, &reply_ok); + + if (reply_ok == KERNEL_SU_OPTION) { + LOGI("KernelSU implementation supports CMD_GET_MANAGER_UID.\n"); + + supports_manager_uid_retrieval = true; + } } else if (version >= 1 && version <= MIN_KSU_VERSION - 1) state->state = TooOld; else state->state = Abnormal; @@ -79,6 +95,18 @@ bool ksu_uid_should_umount(uid_t uid) { } bool ksu_uid_is_manager(uid_t uid) { + /* INFO: If the manager UID is set, we can use it to check if the UID + is the manager UID, which is more reliable than checking + the KSU manager data directory, as spoofed builds of + KernelSU Next have different package names. + */ + if (supports_manager_uid_retrieval) { + if (manager_uid == 0) + prctl(KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, &manager_uid, NULL, NULL); + + return uid == manager_uid; + } + const char *manager_path = NULL; if (variant == KOfficial) manager_path = "/data/user_de/0/me.weishu.kernelsu"; else if (variant == KNext) manager_path = "/data/user_de/0/com.rifsxd.ksunext";