how to replace linux system call by module
TRANSCRIPT
Linux Replace Kernel Function with Module
CGU NCTU aeifkz
大綱
• 看這個可以讓我學到甚麼
• 看這個不會學到甚麼
• 動機
• 背景說明
• 實作 (包含編譯 Linux Kernel以及編寫 Linux Module)
• 結論
• 參考資料
看這個可以讓我學到甚麼
• 如何編譯 Linux kernel 及安裝
• 如何新增自己的 System Call
• 如何在 kernel 裡面放掛勾,之後利用 Module 去做修改
• 如何撰寫及編譯簡單的 Linux Module
看這個不會學到甚麼
• 為什麼是用這些方式新增 System Call (修改哪些檔案等等)
• 為什麼kernel 內的掛勾要用這樣的方式去宣告跟定義
• 這樣 Module 更改的方式有甚麼缺點?
• System Call 要怎麼設計(因為我給的範例真的是爛透了)
動機
• 某次修課必須在 Linux Kernel 底下定義自己的 System Call並且實做
• 但是編譯 Linux Kernel 並安裝實在很花時間,不好的筆電第一次編譯要2個多小時,之後再編也要大概半小時….
• 助教有給如何用 Linux Module的方式來實做,但是 Hint 給的實在太差,但我就是比較笨的學生,所以就自己重寫一篇
背景說明 – 為何要編自己的Kernel
• 可以自己修改 Linux Kernel code ,並且可以新增 System call 的方式提供不同的功能給 User 去使用
• 定義System Call 跟釋出自己的 C Library 有甚麼差別?
我自己是覺得System Call的功能是定義在作業系統層面,因此
1. 理論上作業系統內的任何程式語言都能夠使用這些System Call
(但目前我只會用C/C++去引入)
2. 實作上可以觸碰Linux Kernel 內部的一些結構或是Export 出來的變數
實做 – 新增System Call 及編譯 Kernel
• 環境 : VMware Player + Fedora 14
• 編譯Kernel版本 : 2.6.34.15
• 參考資料 : http://in1.csie.ncu.edu.tw/~hsufh/COURSES/FALL2007/syscall.html
• 以下都是按表操課,所以就只放指令、檔案跟截圖
實做
• 要先有 root 權限
• 下載 Linux Kernel 檔案並且解壓縮,最後切換目錄
• 之後的操作在目錄 /usr/src/kernels/linux-2.6.34.15 底下
cd /usr/src/kernels/wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.34/linux-2.6.34.15.tar.xztar -xf linux-2.6.34.1cd linux-2.6.34.15
vim arch/x86/kernel/syscall_table_32.S
vim arch/x86/include/asm/unistd_32.h
vim arch/x86/include/asm/syscalls.h
vim arch/x86/kernel/hello.c
• 這邊定義了一個被呼叫除了會顯示一些訊息之外,還會回傳1的System Call
• 雖然這個設計爛到爆炸了,但是為了簡單起見,就先將就一下
vim arch/x86/kernel/Makefile
vim /usr/include/asm/unistd_32.h (工作目錄跟前面不一樣)
vim /usr/include/bits/syscall.h(工作目錄跟前面不一樣)
第一次編譯kernel,要等很久…
做完後重開機選擇編譯好的 kernel
寫支程式呼叫這個破爛的System Call…
#include <stdio.h>
#include<sys/syscall.h>
int main(void) {
printf( "system call hello return:%d.\n" , syscall(__NR_hello,2) );
return 0 ;
}
觀看一下System Call 輸出資訊
• 下指令 dmesg (printk 之訊息觀看的方式之一)
重點來了,編譯也太慢了吧…
• 假設編譯一次要30分鐘,一次Lab上課時間3個小時,代表開發者只能失手6次,要不然就要補交…
• 雖然助教提示了用 Linux Module 和 Export_SYMBOL 可以變成只透過 compile/insmod/rmmod 去做開發,但提示也太弱了吧
• 最後參考 reference (搜尋關鍵字 : linux EXPORT_SYMBOL override system call)
http://stackoverflow.com/questions/1196944/can-i-replace-a-linux-kernel-function-with-a-module
所以想法是怎樣?
• 在 Kernel Code 裡面埋下一個錨點 (不專業的術語),並且將其export 給其他 Kernel Code 或是 Kernel Module 去修改
• 錨點要怎麼定義跟埋?用 function pointer 去定義(至於為什麼用這個,就麻煩再另外google)
呼叫也要用 function pointer 方式去呼叫,要不然到時候 Module 額外修改定義不會生效
vim arch/x86/kernel/hello.c
錨點,並且把它指向kernel內部函式
多定義一個函式做跟原本一樣的事情
這邊要用錨點呼叫,若是用logic_sys_hello就沒救了
Export 錨點出來讓 Module 可以引入使用
要多 include module.h,要不然 EXPORT 會失敗
第二次編譯,指令少一些…還是要等有點久
• make
• make modules_install
• make install
•最後重開機….
呼叫破爛的System Call 及觀看結果
• 跟上一次結果應該都一樣,這證明了剛剛下的錨點不影響原本的邏輯
寫一個功能更爛的 Module (開一個新的資料夾來做)
• vim hello.c (part1)
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
MODULE_DESCRIPTION("My Hello World");
MODULE_LICENSE("GPL");
extern int (*p_sys_hello)(int) ;
static int (*tmp_sys_hello)(int) ;
外部引入EXPORT_SYMBOL的變數
暫存原本 kernel 內的定義
寫一個功能更爛的 Module• vim hello.c (part2)
int new_sys_hello( int i) {
printk(KERN_INFO "new system call => %d.\n",i) ;
return 100 ;
}
static int hello_init(void) {
printk(KERN_INFO "Hello, world\n");
tmp_sys_hello = p_sys_hello ;
p_sys_hello = &new_sys_hello ;
return 0;
}
新定義的System Call,會回傳100,很爛我知道
載入module會呼叫的函式,後面會看到設定
暫存原本的定義,替換成新的定義方式
寫一個功能更爛的 Module• vim hello.c (part3)
static void hello_exit(void) {
p_sys_hello = tmp_sys_hello ;
printk(KERN_INFO "Goodbye, cruel world\n");
}
module_init(hello_init) ;
module_exit(hello_exit);
卸載module會呼叫的函式,會回復原本定義
設定載入跟卸載 module要呼叫的函式
再寫一個Makefile• vim Makefile
obj-m += hello.o
KVERSION := $(shell uname -r)
all:
$(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
編譯及載入 module,最後看一下訊息
再次呼叫破爛的System Call 及觀看結果
• 太神奇啦~~~ 數值完全變了,而且不用重新編譯kernel
可以 rmmod hello.ko 再測試一次
• 結果會恢復到載入前的狀態,所以就不截圖了
結論
• 其實沒甚麼結論啦,就準備了一個比較友善的System Call的開發環境
• 至於要怎麼開發 System Call的功能、要把錨點下在哪比較好這些等等就要有勞其他大大分享心得了….
參考資料
• 輕輕鬆鬆學會Linux Kernel Module及TCP/IP 程式設計作者:謝進忠、謝進益, 出版社:全華圖書公司, 出版日期:2005-12-20
(如果你還借得到這本書的話,4.2 如何利用Module來修改Linux的網路核心程式也有提到)