使用模块

时间:2017-06-18 18:43:20

标签: c linux-kernel system-calls kernel-module

在我早期致力于内核编程的过程中,我试图替换/挂钩到ioctl系统调用,目的是记录并最终检查每个完成的ioctl调用。

目标系统是具有内核3.10的mips(o32)系统。

根据我在基于x86的系统中看到的类似项目/示例,我已经找到了一个我认为可行的基本片段。我无法访问System.map,但我注意到了sys_call_table地址,因此我根据目标系统上找到的/proc/kallsyms地址进行了尝试。我知道这个地址会从内核构建变为构建,但这一点并不重要;这仅用于实验目的。

整个模块:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>

static u32 **sct = (u32**)0x80008660; // `grep sys_call_table /proc/kallsyms`

asmlinkage int (*ioctl_orig)(s32 fd, u32 cmd, void* addr);
asmlinkage int ioctl_new(s32 fd, u32 cmd, void* addr)
{
    printk("[IOC] Intercepted ioctl 0x%x to addr 0x%p\n", cmd, addr);
    return ioctl_orig(fd, cmd, addr);
}

static int __init _enter(void)
{
    ioctl_orig = (void*)sct[__NR_ioctl];
    sct[__NR_ioctl] = (u32*)ioctl_new;

    printk("[IOC] Original IOCTL addr: %p\n", ioctl_orig);
    printk("[IOC] New IOCTL addr: %p\n", sct[__NR_ioctl]);
    return 0;
}

static void __exit _exit(void)
{
    sct[__NR_ioctl] = (u32 *)ioctl_orig;
    printk("[IOC] Unloaded\n");
}

module_init(_enter);
module_exit(_exit);
MODULE_LICENSE("GPL");

显然这不起作用,否则我不会在这里刮墙。模块加载正常,printk / _enter的{​​{1}}确实会出现,但是当我以任何方式向内核进行操作时都没有任何反应(我希望看到&# 34;拦截来自_exit的ioctl&#34;消息,这让我相信我正在修改错误的地点。

问题:

  • 显然:我做错了什么?
  • 我可以依靠ioctl_new提供指向系统调用表开头的正确指针吗?
  • 我是否认为与/proc/kallsyms中的sys_ioctl相关联的值应与/proc/kallsyms匹配,或者我错过了哪些内容?
  • 我是否正确投射?
  • 这种修改sctable的方法是否适用于mips?

3 个答案:

答案 0 :(得分:0)

查看arch / mips / kernel / ftrace.c让我相信你需要使用名为“sys32_call_table”的表

答案 1 :(得分:0)

  

我做错了什么?

您正在尝试从内核模块修改系统调用表。这是不安全的,不受支持。不要这样做。

如果要检查系统调用,内核中有许多更好的工具,例如ftraceperfSystemTap。哪一个最适合您将取决于您的具体要求。

答案 2 :(得分:0)

@alexst提供了真实的答案! 根据用于MIPS架构的linux / unistd.h:

#define __NR_Linux 4000
...
#define __NR_ioctl (__NR_Linux + 54)

所以你需要从__NR_ioctl中减去__NR_Linux,例如:

ioctl_orig = (void*)sct[__NR_ioctl-__NR_Linux];