From 8f49898155efaaa33c79a8c19db77ba6bb57c186 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Tue, 11 Nov 2025 01:10:36 +0800 Subject: [PATCH] kernel: Use task work to install fd There are many fd related functions that can sleep, so we have no choice but move operations to task work. Also close fd when copy_to_user fails. Co-authored-by: Wang Han <416810799@qq.com> --- kernel/supercalls.c | 46 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/kernel/supercalls.c b/kernel/supercalls.c index 36d45a57..4ccad162 100644 --- a/kernel/supercalls.c +++ b/kernel/supercalls.c @@ -4,12 +4,15 @@ #include #include #include +#include #include #include #include +#include +#include +#include #include #include -#include #include "arch.h" #include "allowlist.h" @@ -739,9 +742,35 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = { { .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine }; +#ifdef KSU_KPROBES_HOOK + +struct ksu_install_fd_tw { + struct callback_head cb; + int __user *outp; +}; + +static void ksu_install_fd_tw_func(struct callback_head *cb) +{ + struct ksu_install_fd_tw *tw = container_of(cb, struct ksu_install_fd_tw, cb); + int fd = ksu_install_fd(); + pr_info("[%d] install ksu fd: %d\n", current->pid, fd); + + if (copy_to_user(tw->outp, &fd, sizeof(fd))) { + pr_err("install ksu fd reply err\n"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + close_fd(fd); +#else + ksys_close(fd); +#endif + } + + kfree(tw); +} + // downstream: make sure to pass arg as reference, this can allow us to extend things. int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user **arg) { + struct ksu_install_fd_tw *tw; if (magic1 != KSU_INSTALL_MAGIC1) return 0; @@ -752,12 +781,16 @@ int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user // Check if this is a request to install KSU fd if (magic2 == KSU_INSTALL_MAGIC2) { - int fd = ksu_install_fd(); - pr_info("[%d] install ksu fd: %d\n", current->pid, fd); + tw = kzalloc(sizeof(*tw), GFP_ATOMIC); + if (!tw) + return 0; - // downstream: dereference all arg usage! - if (copy_to_user((void __user *)*arg, &fd, sizeof(fd))) { - pr_err("install ksu fd reply err\n"); + tw->outp = (int __user *)*arg; + tw->cb.func = ksu_install_fd_tw_func; + + if (task_work_add(current, &tw->cb, TWA_RESUME)) { + kfree(tw); + pr_warn("install fd add task_work failed\n"); } return 0; @@ -768,7 +801,6 @@ int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user return 0; } -#ifdef KSU_KPROBES_HOOK // Reboot hook for installing fd static int reboot_handler_pre(struct kprobe *p, struct pt_regs *regs) {