如何更新系统调用表以使用我的打开功能

问题描述 投票:0回答:1

我想更新系统调用表以使用我的自定义打开功能,我编写了以下代码

#include <linux/module.h>
#include <linux/kallsyms.h>

MODULE_LICENSE("GPL");
char *sym_name = "sys_call_table";

typedef asmlinkage long (*sys_call_ptr_t)(const struct pt_regs *);
static sys_call_ptr_t *sys_call_table;
typedef asmlinkage long (*custom_open) (const char __user *filename, int flags, umode_t mode);

custom_open old_open;

static asmlinkage long my_open(const char __user *filename, int flags, umode_t mode)
{
    pr_info("%s\n",__func__);
        return old_open(filename, flags, mode);
}

static int __init hello_init(void)
{
    sys_call_table = (sys_call_ptr_t *)kallsyms_lookup_name(sym_name);
    old_open = (custom_open)sys_call_table[__NR_open];
    sys_call_table[__NR_open] = (sys_call_ptr_t)my_open;

    return 0;
}

static void __exit hello_exit(void)
{
    sys_call_table[__NR_open] = (sys_call_ptr_t)old_open;

}

module_init(hello_init);
module_exit(hello_exit);

当我加载模块时,出现以下错误。

[69736.192438] BUG: unable to handle page fault for address: ffffffff98e001d0
[69736.192441] #PF: supervisor write access in kernel mode
[69736.192442] #PF: error_code(0x0003) - permissions violation
[69736.192443] PGD 10460e067 P4D 10460e067 PUD 10460f063 PMD 80000001040000e1 
[69736.192461] Oops: 0003 [#1] SMP PTI
[69736.192463] CPU: 0 PID: 45249 Comm: insmod Tainted: G           OE     5.2.8 #6

我们可以更新系统调用表吗?我们如何解决此类错误

c linux-kernel x86 linux-device-driver system-calls
1个回答
2
投票

您快到了。在Intel x86 CPU中,Control Register CR0有一个特殊的位(称为写保护位),用于控制CPU在特权级别0(内核代码确实在特权级别0上运行)时是否可以写入只读页面。

由于syscall表位于只读页面内,并且默认情况下设置了“写保护”位,因此在执行操作时,您将无法对其进行写操作:

CR0

您将使所有崩溃。

为了正确劫持系统调用,您需要通过在覆盖表条目之前将sys_call_table[__NR_open] = (sys_call_ptr_t)my_open; 寄存器的“写保护”位设置为CR0来禁用写保护,并在完成后重新启用它。正是有两个宏0read_cr0()用于操作所述寄存器。

这是正确的代码:

write_cr0()

上面使用掩码// Temporarily disable write protection write_cr0(read_cr0() & (~0x10000)); // Overwrite the syscall table entry sys_call_table[__NR_open] = /* whatever */; // Re-enable write protection write_cr0(read_cr0() | 0x10000); ,因为“写保护”位是寄存器的第17个最低有效位。

注意,在模块的0x10000init功能中都需要完成上述步骤。

© www.soinside.com 2019 - 2024. All rights reserved.