LinuxOS Project1 = ###### tags: `Course - Linux OS` ## 小組名單 - 第20組 108502532 丁麒源 108502533 廖宥霖 108502530 曹鈞翔 ## 補交內容 ### SYSCALL_DEFINEx 與 asmlinkage SYSCALL_DEFINEx 與 asmlinkage都是讓function call與底層溝通的syscall asmlinkage代表 此函式需遵從 C 語言在此平台下的呼叫慣例,例如x86-32核心中,c function就會從stack而不是register取參數 而SYSCALL_DEFINEx則包含了一個重要的功能,就是讓64 位元的kernel中,32 位元長的值有正確的符號擴展(sign-extended),這是為了防止Linux CVE-2009-0029漏洞被利用。 ## Target ![](https://i.imgur.com/JJgC9Xk.png) - Text (code) Segment: `start_code`(低), `end_code`(高) - Data Segment : `start_data`(低), `end_data`(高) - Bss Segment : `end_data`之上 - Heap Segment : `start_brk`(低), `brk`(高) - Stack Segment : `start_stack`(高), - mmap Segment(share libraries, thread stack...) : `mmap_base`(高) ## ==執行結果== ![](https://i.imgur.com/3tJFSs0.png) * ?代表不確定該處是否存在segment分界 ``` thread: main (pid 2707) virtual addresses of variables: <code()>: '0x555555555249' <data>: '0x555555558010' <bss>: '0x555555558018' <heap>: '0x5555555592a0' <mmmap>: '0x7ffff7ffa000' <stack>: '0x7fffffffddb2' virtual addresses of segment pointers: Code Segment: <start_code>: '0x555555555000' <end_code>: '0x555555555629' Data Segment: <start_data>: '0x555555557d78' <end_data>: '0x555555558015' Heap Segment: <start_brk>: '0x555555559000' <brk>: '0x55555557a000' Stack Segment: <start_stack>: '0x7fffffffdf00' mmap Segment: <mmap_base>: '0x7ffff7fff000' =========================================== thread: t1 (pid 2708) virtual addresses of variables: <code()>: '0x555555555249' <data>: '0x555555558010' <bss>: '0x555555558018' <heap>: '0x7ffff0000b70' <mmmap>: '0x7ffff7fbb000' <stack>: '0x7ffff7d88e42' virtual addresses of segment pointers: Code Segment: <start_code>: '0x555555555000' <end_code>: '0x555555555629' Data Segment: <start_data>: '0x555555557d78' <end_data>: '0x555555558015' Heap Segment: <start_brk>: '0x555555559000' <brk>: '0x55555557a000' Stack Segment: <start_stack>: '0x7fffffffdf00' mmap Segment: <mmap_base>: '0x7ffff7fff000' =========================================== thread: t2 (pid 2709) virtual addresses of variables: <code()>: '0x555555555249' <data>: '0x555555558010' <bss>: '0x555555558018' <heap>: '0x7fffe8000b70' <mmmap>: '0x7ffff7fba000' <stack>: '0x7ffff7587e42' virtual addresses of segment pointers: Code Segment: <start_code>: '0x555555555000' <end_code>: '0x555555555629' Data Segment: <start_data>: '0x555555557d78' <end_data>: '0x555555558015' Heap Segment: <start_brk>: '0x555555559000' <brk>: '0x55555557a000' Stack Segment: <start_stack>: '0x7fffffffdf00' mmap Segment: <mmap_base>: '0x7ffff7fff000' =========================================== ``` ### Variables' address `code` : __all the same, between `start_code` and `end_code`__ `data` : __all the same, between `start_data` and `end_data`__ `bss ` : __all the same, above `end_data`__ `heap` : __3 different address, only main heap between `start_brk` and `brk`, the others below `mmap_base`__ `mmmap`: __3 different address, all below `mmap_base`__ `stack`: __3 different address, only main stack above `mmap_base`, the others below `mmap_base`__ ### Segment pointers' address :::info listed from low address to high address ::: Code segment: - `start_code`: __all the same__ - `end_code`: __all the same__ Data segment: - `start_data`: __all the same__ - `end_data`: __all the same__ Heap segment: - `start_brk`: __all the same__ - `brk`: __all the same__ mmap segment: - `mmap_base`: __all the same__ Stack segment: - `start_stack`: __all the same__ ### 說明&分析 :::success From above result, we can know that threads share the code, data, BSS, heap segments and mmap segment. But they each has their own stack. ::: ***1. Why the results from variable `stack` and `start_stack` are different?*** - Because `start_stack` is pointer to the main thread's stack segment, and `stack` is ponter to address in each thread's stack segment. The thread's stack segment is in the mmap segment. ***2. Address is distribed the same as the following image*** - **increasing** in the order of **code->data->Bss->heap->mmap->stack** ![](https://staff.csie.ncu.edu.tw/hsufh/COURSES/FALL2022/thread-stack.jpg) ***3. `task_struct & mm_struct`*** ![](https://i.imgur.com/9uZf62K.png) - Linux processes are implemented in the kernel as instances of task_struct, the process descriptor. - The mm field in task_struct points to the memory descriptor, mm_struct, which is a summary of a program's memory. - Within the memory descriptor we can find the set of virtual memory areas and the page tables. - We can find each segment's start and end virtual address using virtual memory area. ***4. `mmap()` (user mode function)*** - The dynamic linker uses mmap() *with NULL as the addr argument to load pages of the shared library. The address that the library gets mapped to depends on factors such as: - mmap_base (below stack by default on x86-64, with 28 bits of randomness): see `arch/x86/mm/mmap.c` - the size of the file and previous mappings - Stack space for a new thread is also created by the parent thread with mmap(MAP_ANONYMOUS|MAP_STACK). So they're in the "memory map segment", as we see in our result. - When a thread use malloc(), OS will use mmap() to allocate memory to it. As we see in heap viriable's pointer. ***5. `current` (kernel mode function)*** /include/asm-generic/current.h ![](https://i.imgur.com/kJdUzGE.png) /arch/alpha/include/asm/thread_info.h ![](https://i.imgur.com/SspKZN7.png) ## Kernel and OS version :::success kernel: Linux-5.15.68 OS: Ubuntu-22.04 64bit (WSL) ::: ## Add new system call and Compile kernel ### Download WSL kernel ```bash= wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/rolling-lts/wsl/5.15.68.1.tar.gz tar -xvf WSL2-Linux-Kernel-rolling-lts-wsl-5.15.68.1.tar.gz -C ~/ ``` ### Define new system call ```bash= cd WSL2-Linux-Kernel mkdir get_segment_info nano get_segment_info/get_segment_info.c ``` ### ==Kernel space code== #### `get_segment_info.c` ```c= #include <linux/types.h> #include <linux/syscalls.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/ptrace.h> #include <linux/thread_info.h> #include <asm/current.h> struct segment_info { unsigned long start_code, end_code; unsigned long start_data, end_data; unsigned long start_brk, brk; unsigned long start_stack; unsigned long mmap_base; }; SYSCALL_DEFINE1(get_segment_info, void *, dsi) { struct segment_info si = { .start_code = current->mm->start_code, .end_code = current->mm->end_code, .start_data = current->mm->start_data, .end_data = current->mm->end_data, .start_brk = current->mm->start_brk, .brk = current->mm->brk, .start_stack = current->mm->start_stack, .mmap_base = current->mm->mmap_base, }; if (copy_to_user((struct segment_info *)dsi, &si, sizeof(si))) return -1; return current->pid; } ``` ### Create Makefile for your system call ```bash= nano get_segment_info/Makefile ``` write the following code ```Makefile= obj-y := get_segment_info.o ``` ### Add the home directory of your system call to the main Makefile of the kernel ```bash= nano Makefile ``` Search for `core-y`. In the second result, you will see a series of directories. ``` kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ ``` add ` get_segment_info/` in the end of it ```Makefile= kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ get_segment_info/ ``` ### Add a corresponding function prototype for your system call to the header file of system calls ```bash= nano include/linux/syscalls.h ``` Navigate to the bottom of it and write the following code just above `#endif`. ```c= asmlinkage long sys_get_segment_info(void *); ``` ### Add new system call to kernel's system call table ``` nano arch/x86/entry/syscalls/syscall_64.tbl ``` Add the following code at the end 0f 64-bit system calls (use tab for spacing). ``` 449 common get_segment_info sys_get_segment_info ``` ### Compile and change WSL kernel ```bash= sudo apt install build-essential flex bison dwarves libssl-dev libelf-dev make -j$(nproc) KCONFIG_CONFIG=Microsoft/config-wsl ``` Keep pressing enter to use default config. After compiling, return to host and type the following text in `%USERPROFILE%\.wslconfig` (remember to move the image file to host's directory first): ``` [wsl2] kernel=<path_of_vmlinux> ``` Then reboot WSL. ```powershell= wsl --shutdown && sleep 10 && wsl ``` ## ==User space code== ### `main.c` ```c= #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/syscall.h> #include <pthread.h> #define __NR_get_segment_info 449 struct segment_info { unsigned long start_code, end_code; unsigned long start_data, end_data; unsigned long start_brk, brk; unsigned long start_stack; unsigned long mmap_base; }; char isT1Done = 0; char isT2Done = 0; char *code() { return "code"; } void print_segment_info(char *thread_name) { if (thread_name[1] == '2') { while (!isT1Done) ; } static char data[5] = "data"; static char bss[4]; char *heap = (char *)malloc(sizeof(char) * 5); char *mmmap = mmap(NULL, 5 * sizeof(char), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); char stack[6] = "stack"; struct segment_info si; printf("thread: %s (pid %d)\n", thread_name, syscall(__NR_get_segment_info, &si)); printf("virtual addresses of variables:\n"); printf("<code()>:\t'%p'\n", code); printf("<data>:\t\t'%p'\n", data); printf("<bss>:\t\t'%p'\n", bss); printf("<heap>:\t\t'%p'\n", heap); printf("<mmmap>:\t'%p'\n", mmmap); printf("<stack>:\t'%p'\n", stack); printf("virtual addresses of segment pointers:\n"); printf("Code Segment:\n"); printf("<start_code>:\t'%p'\n", si.start_code); printf("<end_code>:\t'%p'\n", si.end_code); printf("Data Segment:\n"); printf("<start_data>:\t'%p'\n", si.start_data); printf("<end_data>:\t'%p'\n", si.end_data); printf("Heap Segment:\n"); printf("<start_brk>:\t'%p'\n", si.start_brk); printf("<brk>:\t\t'%p'\n", si.brk); printf("Stack Segment:\n"); printf("<start_stack>:\t'%p'\n", si.start_stack); printf("mmap Segment:\n"); printf("<mmap_base>:\t'%p'\n", si.mmap_base); printf("===========================================\n"); if (thread_name[1] == '1') { isT1Done = 1; while (!isT2Done) ; } else if (thread_name[1] == '2') { isT2Done = 1; } free(heap); } int main() { print_segment_info("main"); pthread_t t1, t2; pthread_create(&t1, NULL, print_segment_info, "t1"); pthread_create(&t2, NULL, print_segment_info, "t2"); pthread_join(t1, NULL); pthread_join(t2, NULL); } ``` ## 參考資料 Add new system call: https://dev.to/jasper/adding-a-system-call-to-the-linux-kernel-5-8-1-in-ubuntu-20-04-lts-2ga8 Replacing the WSL Kernel: https://blog.dan.drown.org/replacing-the-wsl-kernel/ problems and solutions: https://blog.csdn.net/qq_36393978/article/details/124274364 https://blog.csdn.net/m0_48958478/article/details/121620449 https://blog.csdn.net/bby1987/article/details/104264285 Others: 奔跑吧 CH 3.1 進程的誕生 https://hackmd.io/@PIFOPlfSS3W_CehLxS3hBQ/S14tx4MqP?fbclid=IwAR2yZqy4A92NegOZUj5frnDXKr_8XG_Y8mXJZXq5lboJG2S3OodFTSmACXg OS Process & Thread (user/kernel) 筆記 https://medium.com/@yovan/os-process-thread-user-kernel-%E7%AD%86%E8%A8%98-aa6e04d35002 linux 内存管理(8) —内存描述符(mm_struct) https://blog.csdn.net/weixin_41028621/article/details/104455327 Linux进程地址管理之mm_struct https://www.cnblogs.com/rofael/archive/2013/04/13/3019153.html Do memory mapping segment and heap grow until they meet each other? https://unix.stackexchange.com/questions/466443/do-memory-mapping-segment-and-heap-grow-until-they-meet-each-other mmap() https://unix.stackexchange.com/questions/466443/do-memory-mapping-segment-and-heap-grow-until-they-meet-each-other https://ithelp.ithome.com.tw/articles/10187260?sc=rss.iron https://www.quora.com/What-factors-decides-the-load-address-of-shared-libraries-like-libc setvbut() https://stackoverflow.com/questions/5876373/using-setvbuf-with-stdin-stream How The Kernel Manages Your Memory https://manybutfinite.com/post/how-the-kernel-manages-your-memory/ malloc() in multi-thread program https://hackmd.io/@ljP_AG30SzmQE5qO-cjcpQ/HkICAjeJg?type=view#%E8%83%8C%E6%99%AF%E7%9F%A5%E8%AD%98%E8%88%87gblic-Malloc%E5%8E%9F%E7%90%86 系統呼叫(system call)的剖析(上) https://alittleresearcher.blogspot.com/2015/02/anatomy-of-a-system-call-part-1.html 什麼是 "asmlinkage"? https://www.jollen.org/blog/2006/10/_asmlinkage.html Linux CVE-2009-0029 漏洞解析 https://blog.csdn.net/hxmhyp/article/details/22619729 Linux 筆記 3 https://hackmd.io/@combo-tw/Linux-%E8%AE%80%E6%9B%B8%E6%9C%83/%2F%40a29654068%2FHyD4Lu_Dr