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>
This commit is contained in:
@@ -4,12 +4,15 @@
|
||||
#include <linux/capability.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/task_work.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user