From 5c96f951b513dfabb61b94623501beeaef1a099e Mon Sep 17 00:00:00 2001 From: Wang Han <416810799@qq.com> Date: Sat, 1 Nov 2025 19:54:52 +0800 Subject: [PATCH] Implement workqueue for unmounting umount schedules, so it cannot be used in kprobe context. --- kernel/core_hook.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index b27624dc..430352a3 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,8 @@ bool ksu_module_mounted = false; +static struct workqueue_struct *ksu_workqueue; + #ifdef CONFIG_COMPAT bool ksu_is_compat __read_mostly = false; #endif @@ -513,6 +516,20 @@ static void try_umount(const char *mnt, bool check_mnt, int flags) ksu_umount_mnt(&path, flags); } +static void do_umount_work(struct work_struct *work) +{ + try_umount("/odm", true, 0); + try_umount("/system", true, 0); + try_umount("/vendor", true, 0); + try_umount("/product", true, 0); + try_umount("/system_ext", true, 0); + try_umount("/data/adb/modules", false, MNT_DETACH); + + // try umount ksu temp path + try_umount("/debug_ramdisk", false, MNT_DETACH); + kfree(work); +} + int ksu_handle_setuid(struct cred *new, const struct cred *old) { if (!new || !old) { @@ -584,14 +601,14 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) // fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and // filter the mountpoint whose target is `/data/adb` - try_umount("/system", true, 0); - try_umount("/vendor", true, 0); - try_umount("/product", true, 0); - try_umount("/system_ext", true, 0); - try_umount("/data/adb/modules", false, MNT_DETACH); + struct work_struct *work = kmalloc(sizeof(struct work_struct), GFP_ATOMIC); + if (!work) { + pr_err("Failed to allocate work\n"); + return 0; + } - // try umount ksu temp path - try_umount("/debug_ramdisk", false, MNT_DETACH); + INIT_WORK(work, do_umount_work); + queue_work(ksu_workqueue, work); get_task_struct(current); // delay fix ksu_set_current_proc_umounted(); @@ -808,6 +825,10 @@ __maybe_unused int ksu_kprobe_exit(void) void __init ksu_core_init(void) { + ksu_workqueue = alloc_workqueue("ksu_umount", WQ_UNBOUND, 0); + if (!ksu_workqueue) { + pr_err("Failed to create ksu workqueue\n"); + } #ifdef CONFIG_KPROBES int rc = ksu_kprobe_init(); if (rc) { @@ -827,4 +848,8 @@ void ksu_core_exit(void) pr_info("ksu_core_exit\n"); ksu_kprobe_exit(); #endif -} \ No newline at end of file + if (ksu_workqueue) { + flush_workqueue(ksu_workqueue); + destroy_workqueue(ksu_workqueue); + } +}