diff --git a/kernel/supercalls.c b/kernel/supercalls.c index 78d7f270..3237a7fe 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" @@ -714,9 +717,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; @@ -727,12 +756,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; @@ -743,7 +776,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) {