[英]How to add a syscall from a kernel module?
好的,所以我試圖從內核模塊向我的Linux添加系統調用。 這是模塊代碼。
asmlinkage int my_syscall() {
printk(KERN_INFO "AWESOME!\n");
return 0;
}
int load() {
unsigned long ** addr;
unsigned long int i = START;
printk(KERN_INFO "IN\n");
while (i < END) {
addr = (unsigned long **)i;
if (addr[__NR_close] == (unsigned long *)sys_close) {
break;
}
i += sizeof(void *);
}
if (i != END) {
addr += __NR_vserver;
struct page * p = virt_to_page(addr);
unsigned long paddr = (unsigned long)page_address(p);
set_memory_rw(paddr, 15);
*addr = &my_syscall;
set_memory_ro(paddr, 15);
}
return 0;
}
void unload() {
printk(KERN_INFO "OUT\n");
}
module_init(load);
module_exit(unload);
因此,我正在尋找sys_call_table
,一旦找到它,我將嘗試覆蓋未實現的syscall( vserver
)。 當我對生成的.ko
insmod
,這是dmesg
所說的:
BUG: unable to handle kernel paging request at ffffffff81801bc0
0xffffffff81801bc0
實際上是我嘗試寫入&my_syscall
的地址。 我不知道我到底在做什么錯,但我想嘗試寫時內存頁面可能仍處於ro
模式下...
我不明白的是以下行:
set_memory_rw(paddr, 15);
這里應該怎么辦?
您不能更改物理地址的屬性!
也許以下代碼是正確的:
set_memory_rw(addr, 15);
(在這種情況下,您不需要物理地址“ paddr”,也不需要頁面“ p”。)
或者,您可以嘗試第二次在內核空間中映射物理地址。
您應該在“ unload()”函數中恢復原始指針!
如果0xffffffff81801bc0是您傳遞給set_memory_rw()的實際地址,則絕對是錯誤的值。 該地址應四舍五入到PAGE_MASK邊界,即頁面的起始地址,對於64位系統,通常以4個零結尾。
set_memory_rw()使用內存頁表的U / S位進行操作。 但是x86 / amd64 CPU還有另一個屬性:WP位(在cr0內部)。 根據Intel手冊,WP位將覆蓋內存頁表屬性,即,啟用/禁用WP位仍將起作用,無論內存是否為只讀。 但是WP位是每個CPU的,因此請仔細同步您的內存訪問,以便在更改內存內容時,另一個CPU不會讀取它。 (對於您未使用的系統調用號碼,這應該沒問題)。
看來您錯過了系統調用的實現。 只需看一下http://arvindsraj.wordpress.com/2012/10/05/adding-hello-world-system-call-to-linux/ ,它逐步說明了實現系統調用的過程並檢查您是否有是否正確執行了所有步驟。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.