kernel: Improve dynamic manager functions and logging

This commit is contained in:
ShirkNeko
2025-09-14 19:31:21 +08:00
parent fb2ad3ec7b
commit f8abf097d7
4 changed files with 179 additions and 140 deletions

View File

@@ -74,6 +74,7 @@ struct my_dir_context {
void *private_data;
int depth;
int *stop;
bool found_dynamic_manager;
};
// https://docs.kernel.org/filesystems/porting.html
// filldir_t (readdir callbacks) calling conventions have changed. Instead of returning 0 or -E... it returns bool now. false means "no more" (as -E... used to) and true - "keep going" (as 0 in old calling conventions). Rationale: callers never looked at specific -E... values anyway. -> iterate_shared() instances require no changes at all, all filldir_t ones in the tree converted.
@@ -153,7 +154,7 @@ static void crown_manager(const char *apk, struct list_head *uid_data,
pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n",
pkg, np->uid, signature_index);
// Dynamic Sign index (1) or multi-manager signatures (2+)
// Dynamic Sign index (100) or multi-manager signatures (>= 2)
if (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2) {
ksu_add_manager(np->uid, signature_index);
@@ -468,6 +469,7 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
// Check for dynamic sign or multi-manager signatures
if (is_multi_manager && (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2)) {
my_ctx->found_dynamic_manager = true;
crown_manager(dirpath, my_ctx->private_data, signature_index);
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
@@ -478,12 +480,17 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
}
} else if (is_manager_apk(dirpath)) {
crown_manager(dirpath, my_ctx->private_data, 0);
*my_ctx->stop = 1;
if (!my_ctx->found_dynamic_manager && !ksu_is_dynamic_manager_enabled()) {
*my_ctx->stop = 1;
}
// Manager found, clear APK cache list
list_for_each_entry_safe(pos, n, &apk_path_hash_list, list) {
list_del(&pos->list);
kfree(pos);
if (!ksu_is_dynamic_manager_enabled()) {
list_for_each_entry_safe(pos, n, &apk_path_hash_list, list) {
list_del(&pos->list);
kfree(pos);
}
}
} else {
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
@@ -506,6 +513,7 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
INIT_LIST_HEAD(&data_path_list);
INIT_LIST_HEAD(&apk_path_hash_list);
unsigned long data_app_magic = 0;
bool found_dynamic_manager = false;
// Initialize APK cache list
struct apk_path_hash *pos, *n;
@@ -528,7 +536,8 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
.parent_dir = pos->dirpath,
.private_data = uid_data,
.depth = pos->depth,
.stop = &stop };
.stop = &stop,
.found_dynamic_manager = false };
struct file *file;
if (!stop) {
@@ -558,13 +567,17 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
iterate_dir(file, &ctx.ctx);
filp_close(file, NULL);
if (ctx.found_dynamic_manager) {
found_dynamic_manager = true;
}
}
skip_iterate:
list_del(&pos->list);
if (pos != &data)
kfree(pos);
}
}
}
// clear apk_path_hash_list unconditionally
pr_info("search manager: cleanup!\n");
@@ -621,12 +634,16 @@ static void track_throne_function(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_dynamic_manager_enabled()) {
dynamic_manager_exist = ksu_has_dynamic_managers();
if (!dynamic_manager_exist) {
list_for_each_entry (np, &uid_list, list) {
// 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;
if (ksu_is_any_manager(np->uid) && np->uid != ksu_get_manager_uid()) {
dynamic_manager_exist = true;
break;
}
}
}
}
@@ -635,17 +652,25 @@ static void track_throne_function(void)
if (ksu_is_manager_uid_valid()) {
pr_info("manager is uninstalled, invalidate it!\n");
ksu_invalidate_manager_uid();
goto prune;
}
pr_info("Searching manager...\n");
search_manager("/data/app", 2, &uid_list);
pr_info("Search manager finished\n");
} else if (!dynamic_manager_exist && ksu_is_dynamic_manager_enabled()) {
// Always perform search when called from dynamic manager rescan
goto prune;
}
// Always perform search when called from dynamic manager rescan
if (ksu_is_dynamic_manager_enabled() && !dynamic_manager_exist) {
pr_info("Dynamic sign enabled, Searching manager...\n");
search_manager("/data/app", 2, &uid_list);
pr_info("Search Dynamic sign manager finished\n");
}
// If traditional manager exists but no dynamic manager instances found, do a full search
if (manager_exist && ksu_is_dynamic_manager_enabled() && !dynamic_manager_exist) {
pr_info("Searching manager...\n");
search_manager("/data/app", 2, &uid_list);
pr_info("Search manager finished\n");
}
prune:
// then prune the allowlist