LINUX PROJECT 1

Deadline : 11/9 23:59

Demo schedule: link


task_struct 結構如上

作業要求

  1. 寫一個 system call 從 kernel space 找出指定 process(task) 的 code(text) 段的位址

Reference 僅適用於 3.X 版,例如以下步驟:

$ vim include/linux/syscalls.h
在最下面(#endif前)新增一行
// asmlinkage int helloworld(void); 
asmlinkage int sys_helloworld(void);    // 4.X/5.X 版須加上 sys_ 前綴
                                        // 否則編譯會找不到 reference 而報錯

helloworld.c 定義

$ vim mycall/helloworld.c
asmlinkage int __x64_sys_helloworld(void) // 5.X 版 syscall 定義

以上改前綴的方式其實算是"偷吃步",詳情請見 macro SYSCALL_DEFINEn

請注意⚠每個版本編譯 kernel 方法不盡相同,請找適合自己版本的方法

  1. user 段程式利用 system call 傳入 pid 並取得結果放至 user space 的 buffer 上,再輸出至 terminal 上。

Example

範例如下:

  • system call 範例程式

init_task 開始遍歷 task_list 至指定 task,傳出指定資料至指定記憶體段。

/* * Example for linux kernel 4.15 */ #include <linux/kernel.h> #include <linux/string.h> #include <linux/uaccess.h> #include <linux/init_task.h> // you need to pass this data struct to userspace and print on terminal struct data_segment { unsigned long start_code; unsigned long end_code; }; asmlinkage int pass_kernel_data(pid_t user_pid, void* __user user_address) { ... for_each_process(task) { if(task->pid == user_pid) { //what is x1, x2, x3 my_data_segment.start_code = x1->x2->x3; //what is y1, y2, y3 my_data_segment.end_code = y1->y2->y3; // xxx is key function xxx(user_address, &my_data_segment, sizeof(struct data_segment)); } } ... return 0; }
  • user space 程式範例:
#include <syscall.h> #include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <time.h> struct data_segment { unsigned long start_code; unsigned long end_code; }; int main() { struct data_segment my_data_segment; int a = syscall(???, getpid(), (void*)&my_data_segment); printf("Start: %lx\nEnd: %lx\n", my_data_segment.start_code, my_data_segment.end_code); return 0; }

以上程式碼根據 kernel 版本會有些許不同

有問題可以上聊天室發問或是 email 助教

Select a repo