2017-06-18 73 views
0

在我的早期努力進入內核編程我試圖替換/掛鉤到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嗎?
+0

「我在做什麼了?」在x86上,要執行相同的操作,必須通過某些asm行禁用頁面保護。我認爲在mips上有一些等價物。 – purplepsycho

+0

「我可以依賴'/ proc/kallsyms' ...嗎?「您的系統上是否存在」kallsyms_lookup_name(「sys_call_table」)「函數?它應該返回您想要的。(https://stackoverflow.com/a/39202118/1212012) – purplepsycho

+0

注意到cr0頁面保護位x86,儘管我還沒有在MIPS上找到類似機制的證據 – bjorn

回答

0

望着牌坊/ MIPS /內核/ ftrace.c使我相信,你需要使用一個名爲「sys32_call_table」

+0

沒有提到3.10源代碼樹中的sys32_call_table,似乎是一個更近的事情? – bjorn

+0

確實沒有在3.10,但我認爲你需要檢查系統調用參數。看起來像O32你需要從系統調用號減去__NR_O32_Linux?我不太確定,因爲我沒有用過MIPS。 https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable/+/linux-3.10.y/arch/mips/include/uapi/asm/unistd.h #380無論哪種方式,你都可以直接實現你的鉤子在「fs/ioctl.c」和「fs/compat_ioctl.c」中。如果你想要一個模塊,你可以通過security_file_ioctl – alexst

0

我在做什麼錯表?

您正試圖從內核模塊修改系統調用表。這是不安全和不受支持的。不要這樣做。

如果您想檢查系統調用,那麼在內核中有許多更好的工具可用,例如ftrace,perfSystemTap。哪一個最適合你,取決於你的具體要求。

+0

實現一個像SELinux或者Tomoyo這樣的可加載安全模塊。完全意識到這是一個陰暗的實踐。將進一步研究,看看是否可以幫助我們。目標系統上沒有其他兩個選項(硬化嵌入式內核)。 – bjorn

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];