在我早期致力于内核编程的过程中,我试图替换/挂钩到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
匹配,或者我错过了哪些内容?答案 0 :(得分:0)
查看arch / mips / kernel / ftrace.c让我相信你需要使用名为“sys32_call_table”的表
答案 1 :(得分:0)
我做错了什么?
您正在尝试从内核模块修改系统调用表。这是不安全的,不受支持。不要这样做。
如果要检查系统调用,内核中有许多更好的工具,例如ftrace,perf和SystemTap。哪一个最适合您将取决于您的具体要求。
答案 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];