From 1439e486a1021e29048c8c89e54a84bdbaf98489 Mon Sep 17 00:00:00 2001 From: weishu Date: Tue, 4 Nov 2025 13:31:45 +0000 Subject: [PATCH] kernel: rework umount with task_work --- kernel/core_hook.c | 67 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index a6d8f7da..83b75dcd 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -1,4 +1,6 @@ -#include "linux/slab.h" +#include +#include +#include #include #include #include @@ -508,8 +510,44 @@ static void try_umount(const char *mnt, bool check_mnt, int flags) ksu_umount_mnt(&path, flags); } +struct umount_tw { + struct callback_head cb; + const struct cred *old_cred; +}; + +static void umount_tw_func(struct callback_head *cb) +{ + struct umount_tw *tw = container_of(cb, struct umount_tw, cb); + const struct cred *saved = NULL; + if (tw->old_cred) { + saved = override_creds(tw->old_cred); + } + + // fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and + // filter the mountpoint whose target is `/data/adb` + 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("/data/adb/kpm", false, MNT_DETACH); + + // try umount ksu temp path + try_umount("/debug_ramdisk", false, MNT_DETACH); + + if (saved) + revert_creds(saved); + + if (tw->old_cred) + put_cred(tw->old_cred); + + kfree(tw); +} + int ksu_handle_setuid(struct cred *new, const struct cred *old) { + struct umount_tw *tw; if (!new || !old) { return 0; } @@ -587,19 +625,21 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val, current->pid); #endif - // fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and - // filter the mountpoint whose target is `/data/adb` - 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); + tw = kmalloc(sizeof(*tw), GFP_ATOMIC); + if (!tw) + return 0; - try_umount("/data/adb/modules", false, MNT_DETACH); - try_umount("/data/adb/kpm", false, MNT_DETACH); + tw->old_cred = get_current_cred(); + tw->cb.func = umount_tw_func; - // try umount ksu temp path - try_umount("/debug_ramdisk", false, MNT_DETACH); + int err = task_work_add(current, &tw->cb, TWA_RESUME); + if (err) { + if (tw->old_cred) { + put_cred(tw->old_cred); + } + kfree(tw); + pr_warn("unmount add task_work failed\n"); + } return 0; } @@ -653,7 +693,8 @@ static struct kprobe reboot_kp = { }; // 2. cap_task_fix_setuid hook for handling setuid -static int cap_task_fix_setuid_handler_pre(struct kprobe *p, struct pt_regs *regs) +static int cap_task_fix_setuid_handler_pre(struct kprobe *p, + struct pt_regs *regs) { struct cred *new = (struct cred *)PT_REGS_PARM1(regs); const struct cred *old = (const struct cred *)PT_REGS_PARM2(regs);