kernel: Add Hot Update Rescan Manager feature for dynamic signatures
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "klog.h" // IWYU pragma: keep
|
||||
#include "kernel_compat.h"
|
||||
#include "manager.h"
|
||||
#include "throne_tracker.h"
|
||||
|
||||
#define MAX_MANAGERS 2
|
||||
|
||||
@@ -34,10 +35,11 @@ static struct manager_info active_managers[MAX_MANAGERS];
|
||||
static DEFINE_SPINLOCK(managers_lock);
|
||||
static DEFINE_SPINLOCK(dynamic_sign_lock);
|
||||
|
||||
// Work queues for persistent storage
|
||||
// Work queues for persistent storage and manager rescanning
|
||||
static struct work_struct ksu_save_dynamic_sign_work;
|
||||
static struct work_struct ksu_load_dynamic_sign_work;
|
||||
static struct work_struct ksu_clear_dynamic_sign_work;
|
||||
static struct work_struct ksu_rescan_manager_work;
|
||||
|
||||
bool ksu_is_dynamic_sign_enabled(void)
|
||||
{
|
||||
@@ -162,7 +164,7 @@ int ksu_get_manager_signature_index(uid_t uid)
|
||||
return signature_index;
|
||||
}
|
||||
|
||||
static void clear_all_managers(void)
|
||||
static void clear_dynamic_managers_only(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
@@ -215,6 +217,29 @@ int ksu_get_active_managers(struct manager_list_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Manager rescanning work handler
|
||||
void ksu_rescan_manager_work_handler(struct work_struct *work)
|
||||
{
|
||||
pr_info("Starting manager rescan for dynamic sign changes\n");
|
||||
|
||||
// Clear only dynamic managers, preserve default manager
|
||||
clear_dynamic_managers_only();
|
||||
|
||||
// Note: We preserve the traditional manager (index 0) and only rescan for dynamic managers
|
||||
pr_info("Preserved traditional manager, rescanning for dynamic managers\n");
|
||||
|
||||
// Trigger manager scanning
|
||||
ksu_track_throne();
|
||||
|
||||
pr_info("Manager rescan completed\n");
|
||||
}
|
||||
|
||||
bool ksu_trigger_manager_rescan(void)
|
||||
{
|
||||
return ksu_queue_work(&ksu_rescan_manager_work);
|
||||
}
|
||||
|
||||
static void do_save_dynamic_sign(struct work_struct *work)
|
||||
{
|
||||
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
|
||||
@@ -413,6 +438,10 @@ int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
|
||||
persistent_dynamic_sign();
|
||||
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
|
||||
config->size, config->hash);
|
||||
|
||||
// Always trigger manager rescan when dynamic sign is set
|
||||
pr_info("Dynamic sign set, triggering manager rescan\n");
|
||||
ksu_trigger_manager_rescan();
|
||||
break;
|
||||
|
||||
case DYNAMIC_SIGN_OP_GET:
|
||||
@@ -437,12 +466,18 @@ int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
|
||||
strcpy(dynamic_sign.hash, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
dynamic_sign.is_set = 0;
|
||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||
clear_all_managers();
|
||||
|
||||
// Clear only dynamic managers, preserve default manager
|
||||
clear_dynamic_managers_only();
|
||||
|
||||
// Clear file using the same method as save
|
||||
clear_dynamic_sign_file();
|
||||
|
||||
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
|
||||
|
||||
// Always trigger manager rescan when dynamic sign is cleared
|
||||
pr_info("Dynamic sign cleared, triggering manager rescan\n");
|
||||
ksu_trigger_manager_rescan();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -465,22 +500,24 @@ void ksu_dynamic_sign_init(void)
|
||||
INIT_WORK(&ksu_save_dynamic_sign_work, do_save_dynamic_sign);
|
||||
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign);
|
||||
INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign_file);
|
||||
INIT_WORK(&ksu_rescan_manager_work, ksu_rescan_manager_work_handler);
|
||||
|
||||
// Initialize manager slots
|
||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||
active_managers[i].is_active = false;
|
||||
}
|
||||
|
||||
pr_info("Dynamic sign initialized with conditional multi-manager support\n");
|
||||
pr_info("Dynamic sign initialized with conditional multi-manager support and rescan capability\n");
|
||||
}
|
||||
|
||||
void ksu_dynamic_sign_exit(void)
|
||||
{
|
||||
clear_all_managers();
|
||||
// Clear only dynamic managers on exit, preserve default manager
|
||||
clear_dynamic_managers_only();
|
||||
|
||||
// Save current config before exit
|
||||
do_save_dynamic_sign(NULL);
|
||||
pr_info("Dynamic sign exited with persistent storage\n");
|
||||
pr_info("Dynamic sign exited, cleared dynamic managers, preserved default manager\n");
|
||||
}
|
||||
|
||||
// Get dynamic sign configuration for signature verification
|
||||
|
||||
@@ -37,4 +37,8 @@ int ksu_get_active_managers(struct manager_list_info *info);
|
||||
// Multi-manager APK verification
|
||||
bool ksu_is_multi_manager_apk(char *path, int *signature_index);
|
||||
|
||||
// Manager rescanning functionality
|
||||
bool ksu_trigger_manager_rescan(void);
|
||||
void ksu_rescan_manager_work_handler(struct work_struct *work);
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "manager.h"
|
||||
#include "throne_tracker.h"
|
||||
#include "kernel_compat.h"
|
||||
#include "dynamic_sign.h"
|
||||
|
||||
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
||||
|
||||
@@ -385,7 +386,7 @@ void track_throne()
|
||||
struct uid_data *np;
|
||||
struct uid_data *n;
|
||||
|
||||
// first, check if manager_uid exist!
|
||||
// Check if any manager exists (traditional or dynamic)
|
||||
bool manager_exist = false;
|
||||
list_for_each_entry (np, &uid_list, list) {
|
||||
// if manager is installed in work profile, the uid in packages.list is still equals main profile
|
||||
@@ -395,9 +396,15 @@ void track_throne()
|
||||
manager_exist = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ksu_is_any_manager(np->uid)) {
|
||||
manager_exist = true;
|
||||
}
|
||||
|
||||
// Check for dynamic managers
|
||||
if (!manager_exist && ksu_is_dynamic_sign_enabled()) {
|
||||
list_for_each_entry (np, &uid_list, list) {
|
||||
if (ksu_is_any_manager(np->uid)) {
|
||||
manager_exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,6 +417,11 @@ void track_throne()
|
||||
pr_info("Searching manager...\n");
|
||||
search_manager("/data/app", 2, &uid_list);
|
||||
pr_info("Search manager finished\n");
|
||||
} else {
|
||||
// Always perform search when called from dynamic sign rescan
|
||||
pr_info("Performing manager search (may be from dynamic sign rescan)\n");
|
||||
search_manager("/data/app", 2, &uid_list);
|
||||
pr_info("Manager search completed\n");
|
||||
}
|
||||
|
||||
prune:
|
||||
|
||||
Reference in New Issue
Block a user