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 "klog.h" // IWYU pragma: keep
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
|
#include "throne_tracker.h"
|
||||||
|
|
||||||
#define MAX_MANAGERS 2
|
#define MAX_MANAGERS 2
|
||||||
|
|
||||||
@@ -34,10 +35,11 @@ static struct manager_info active_managers[MAX_MANAGERS];
|
|||||||
static DEFINE_SPINLOCK(managers_lock);
|
static DEFINE_SPINLOCK(managers_lock);
|
||||||
static DEFINE_SPINLOCK(dynamic_sign_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_save_dynamic_sign_work;
|
||||||
static struct work_struct ksu_load_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_clear_dynamic_sign_work;
|
||||||
|
static struct work_struct ksu_rescan_manager_work;
|
||||||
|
|
||||||
bool ksu_is_dynamic_sign_enabled(void)
|
bool ksu_is_dynamic_sign_enabled(void)
|
||||||
{
|
{
|
||||||
@@ -162,7 +164,7 @@ int ksu_get_manager_signature_index(uid_t uid)
|
|||||||
return signature_index;
|
return signature_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_all_managers(void)
|
static void clear_dynamic_managers_only(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
@@ -215,6 +217,29 @@ int ksu_get_active_managers(struct manager_list_info *info)
|
|||||||
return 0;
|
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)
|
static void do_save_dynamic_sign(struct work_struct *work)
|
||||||
{
|
{
|
||||||
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
|
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
|
||||||
@@ -413,6 +438,10 @@ int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
|
|||||||
persistent_dynamic_sign();
|
persistent_dynamic_sign();
|
||||||
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
|
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
|
||||||
config->size, config->hash);
|
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;
|
break;
|
||||||
|
|
||||||
case DYNAMIC_SIGN_OP_GET:
|
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");
|
strcpy(dynamic_sign.hash, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
dynamic_sign.is_set = 0;
|
dynamic_sign.is_set = 0;
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
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 file using the same method as save
|
||||||
clear_dynamic_sign_file();
|
clear_dynamic_sign_file();
|
||||||
|
|
||||||
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
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_save_dynamic_sign_work, do_save_dynamic_sign);
|
||||||
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_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_clear_dynamic_sign_work, do_clear_dynamic_sign_file);
|
||||||
|
INIT_WORK(&ksu_rescan_manager_work, ksu_rescan_manager_work_handler);
|
||||||
|
|
||||||
// Initialize manager slots
|
// Initialize manager slots
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
active_managers[i].is_active = false;
|
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)
|
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
|
// Save current config before exit
|
||||||
do_save_dynamic_sign(NULL);
|
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
|
// 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
|
// Multi-manager APK verification
|
||||||
bool ksu_is_multi_manager_apk(char *path, int *signature_index);
|
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
|
#endif
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "throne_tracker.h"
|
#include "throne_tracker.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
#include "dynamic_sign.h"
|
||||||
|
|
||||||
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
||||||
|
|
||||||
@@ -385,7 +386,7 @@ void track_throne()
|
|||||||
struct uid_data *np;
|
struct uid_data *np;
|
||||||
struct uid_data *n;
|
struct uid_data *n;
|
||||||
|
|
||||||
// first, check if manager_uid exist!
|
// Check if any manager exists (traditional or dynamic)
|
||||||
bool manager_exist = false;
|
bool manager_exist = false;
|
||||||
list_for_each_entry (np, &uid_list, list) {
|
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
|
// 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;
|
manager_exist = true;
|
||||||
break;
|
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");
|
pr_info("Searching manager...\n");
|
||||||
search_manager("/data/app", 2, &uid_list);
|
search_manager("/data/app", 2, &uid_list);
|
||||||
pr_info("Search manager finished\n");
|
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:
|
prune:
|
||||||
|
|||||||
Reference in New Issue
Block a user