在我的早期努力進入內核編程我試圖替換/掛鉤到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");
顯然,這並不工作,否則我就不會在這裏刮牆。模塊加載正常,並且從_enter
/_exit
確實出現,但是當我以任何方式對內核執行ioctls時(我期望看到來自ioctl_new
的「Intercepted ioctl」消息),沒有任何反應,這導致我相信我正在修改錯誤的地方。
問題:
- 很明顯:我在做什麼錯?
- 我可以依靠
/proc/kallsyms
提供指向syscall表開頭的正確指針嗎? - 我是否正確地認爲
sys_ioctl
在/proc/kallsyms
中的值應該與*sct[__NR_ioctl]
匹配,或者我錯過了什麼? - 我能正確投射嗎?
- 這種修改sctable的方法甚至適用於mips嗎?
「我在做什麼了?」在x86上,要執行相同的操作,必須通過某些asm行禁用頁面保護。我認爲在mips上有一些等價物。 – purplepsycho
「我可以依賴'/ proc/kallsyms' ...嗎?「您的系統上是否存在」kallsyms_lookup_name(「sys_call_table」)「函數?它應該返回您想要的。(https://stackoverflow.com/a/39202118/1212012) – purplepsycho
注意到cr0頁面保護位x86,儘管我還沒有在MIPS上找到類似機制的證據 – bjorn