From fc5cd9e9ed3e021c330a8399a88f411d831d7b9a Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sat, 6 Sep 2025 15:06:10 +0800 Subject: [PATCH] kernel: Reworking Dynamic Manager Index Configuration --- kernel/apk_sign.c | 71 +++++++++++++++++++++++++++++++++------- kernel/dynamic_manager.c | 2 +- kernel/dynamic_manager.h | 11 +++++++ kernel/manager.h | 3 +- kernel/throne_tracker.c | 9 +++-- 5 files changed, 79 insertions(+), 17 deletions(-) diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index be24a406..fd272828 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -30,7 +30,6 @@ static struct apk_sign_key { const char *sha256; } apk_sign_keys[] = { {EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // SukiSU - {EXPECTED_SIZE_OTHER, EXPECTED_HASH_OTHER}, // Dynamic Sign #ifdef CONFIG_KSU_MULTI_MANAGER_SUPPORT {EXPECTED_SIZE_WEISHU, EXPECTED_HASH_WEISHU}, // Official {EXPECTED_SIZE_5EC1CFF, EXPECTED_HASH_5EC1CFF}, // 5ec1cff/KernelSU @@ -88,6 +87,54 @@ static int ksu_sha256(const unsigned char *data, unsigned int datalen, crypto_free_shash(alg); return ret; } + + +static struct dynamic_sign_key dynamic_sign = DYNAMIC_SIGN_DEFAULT_CONFIG; + +static bool check_dynamic_sign(struct file *fp, u32 size4, loff_t *pos, int *matched_index) +{ + struct dynamic_sign_key current_dynamic_key = dynamic_sign; + + if (ksu_get_dynamic_manager_config(¤t_dynamic_key.size, ¤t_dynamic_key.hash)) { + pr_debug("Using dynamic manager config: size=0x%x, hash=%.16s...\n", + current_dynamic_key.size, current_dynamic_key.hash); + } + + if (size4 != current_dynamic_key.size) { + return false; + } + +#define CERT_MAX_LENGTH 1024 + char cert[CERT_MAX_LENGTH]; + if (size4 > CERT_MAX_LENGTH) { + pr_info("cert length overlimit\n"); + return false; + } + + ksu_kernel_read_compat(fp, cert, size4, pos); + + unsigned char digest[SHA256_DIGEST_SIZE]; + if (ksu_sha256(cert, size4, digest) < 0) { + pr_info("sha256 error\n"); + return false; + } + + char hash_str[SHA256_DIGEST_SIZE * 2 + 1]; + hash_str[SHA256_DIGEST_SIZE * 2] = '\0'; + bin2hex(hash_str, digest, SHA256_DIGEST_SIZE); + + pr_info("sha256: %s, expected: %s, index: dynamic\n", hash_str, current_dynamic_key.hash); + + if (strcmp(current_dynamic_key.hash, hash_str) == 0) { + if (matched_index) { + *matched_index = DYNAMIC_SIGN_INDEX; + } + return true; + } + + return false; +} + static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index) { int i; @@ -109,18 +156,18 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length *offset += 0x4 * 2; + if (ksu_is_dynamic_manager_enabled()) { + loff_t temp_pos = *pos; + if (check_dynamic_sign(fp, *size4, &temp_pos, matched_index)) { + *pos = temp_pos; + *offset += *size4; + return true; + } + } + for (i = 0; i < ARRAY_SIZE(apk_sign_keys); i++) { sign_key = apk_sign_keys[i]; - if (i == 1) { // Dynamic Sign indexing - unsigned int size; - const char *hash; - if (ksu_get_dynamic_manager_config(&size, &hash)) { - sign_key.size = size; - sign_key.sha256 = hash; - } - } - if (*size4 != sign_key.size) continue; *offset += *size4; @@ -335,8 +382,8 @@ clean: } if (check_multi_manager) { - // 0: ShirkNeko/SukiSU, 1: Dynamic Sign - if (matched_index == 0 || matched_index == 1) { + // 0: ShirkNeko/SukiSU, DYNAMIC_SIGN_INDEX : Dynamic Sign + if (matched_index == 0 || matched_index == DYNAMIC_SIGN_INDEX) { pr_info("Multi-manager APK detected (dynamic_manager enabled): signature_index=%d\n", matched_index); return true; } diff --git a/kernel/dynamic_manager.c b/kernel/dynamic_manager.c index 5705fef8..6f34d192 100644 --- a/kernel/dynamic_manager.c +++ b/kernel/dynamic_manager.c @@ -142,7 +142,7 @@ int ksu_get_manager_signature_index(uid_t uid) // Check traditional manager first if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) { - return 1; + return DYNAMIC_SIGN_INDEX; } if (!ksu_is_dynamic_manager_enabled()) { diff --git a/kernel/dynamic_manager.h b/kernel/dynamic_manager.h index 5e9201a8..1b5a5cbd 100644 --- a/kernel/dynamic_manager.h +++ b/kernel/dynamic_manager.h @@ -7,6 +7,17 @@ #define DYNAMIC_MANAGER_FILE_MAGIC 0x7f445347 // 'DSG', u32 #define DYNAMIC_MANAGER_FILE_VERSION 1 // u32 #define KERNEL_SU_DYNAMIC_MANAGER "/data/adb/ksu/.dynamic_manager" +#define DYNAMIC_SIGN_INDEX 100 + +struct dynamic_sign_key { + unsigned int size; + const char *hash; +}; + +#define DYNAMIC_SIGN_DEFAULT_CONFIG { \ + .size = 0x300, \ + .hash = "0000000000000000000000000000000000000000000000000000000000000000" \ +} struct dynamic_manager_config { unsigned int size; diff --git a/kernel/manager.h b/kernel/manager.h index 81871b69..57f43418 100644 --- a/kernel/manager.h +++ b/kernel/manager.h @@ -20,7 +20,8 @@ static inline bool ksu_is_manager_uid_valid(void) static inline bool is_manager(void) { - return unlikely(ksu_is_any_manager(current_uid().val) || ksu_manager_uid == current_uid().val); + return unlikely(ksu_is_any_manager(current_uid().val) || + (ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val)); } static inline uid_t ksu_get_manager_uid(void) diff --git a/kernel/throne_tracker.c b/kernel/throne_tracker.c index 51e66780..19edc8cf 100644 --- a/kernel/throne_tracker.c +++ b/kernel/throne_tracker.c @@ -88,7 +88,8 @@ static void crown_manager(const char *apk, struct list_head *uid_data, int signa if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) { pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n", pkg, np->uid, signature_index); - if (signature_index == 1 || signature_index == 2) { + // Dynamic Sign index (1) or multi-manager signatures (2+) + if (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2) { ksu_add_manager(np->uid, signature_index); if (!ksu_is_manager_uid_valid()) { @@ -205,7 +206,8 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name, pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n", dirpath, is_multi_manager, signature_index); - if (is_multi_manager && (signature_index == 1 || signature_index == 2)) { + // Check for dynamic sign or multi-manager signatures + if (is_multi_manager && (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2)) { crown_manager(dirpath, my_ctx->private_data, signature_index); struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC); @@ -406,7 +408,8 @@ void track_throne(void) // Check for dynamic managers if (!dynamic_manager_exist && ksu_is_dynamic_manager_enabled()) { list_for_each_entry (np, &uid_list, list) { - if (ksu_is_any_manager(np->uid)) { + // Check if this uid is a dynamic manager (not the traditional manager) + if (ksu_is_any_manager(np->uid) && np->uid != ksu_get_manager_uid()) { dynamic_manager_exist = true; break; }