It is really too pit, really want to Tucao about this operation system practice, each time is compile the kernel. The textbook was written in 2009, all the code before kernel 3.3.
I record the system call experiment, hope you can avoid stepping on the pit.
Method 1: kernel compilation
Here I give you a link. This blog is well written and really works perfectly: https://blog.csdn.net/qq_41175905/article/details/80529245
Method 2: add kernel through module
1. Write in any folder here
2. Take hello.c as an example. Here I read some blogs and use their code directly. I just need to modify some old versions. For example, movl is written as movq, register eax is written as rax, CR0 & = 0xfffeffff is written as 0xffffffffffffffffffff, that is, add 8 f's.
Please note that the address of sys call table below should be changed to the address displayed on your computer at this time. The address of X cannot be omitted, and will change every time you restart.
The command to query the syscall table address is:
sudo cat /proc/kallsyms | grep sys_call_table
hello.c
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/unistd.h> #include <linux/sched.h> MODULE_LICENSE("Dual BSD/GPL"); #Define sys? Call? Table? Address 0xffffffffa04001a0 / / address corresponding to sys? Call? Table #define NUM 223 / / the system call number is 223 int orig_cr0; //Used to store the original value of cr0 register unsigned long *sys_call_table_my=0; static int(*anything_saved)(void); //Define a function pointer to hold a system call static int clear_cr0(void) //Set bit 17 of cr0 register to 0 (kernel space writable) { unsigned int cr0=0; unsigned int ret; asm volatile("movq %%cr0,%%rax":"=a"(cr0));//Move the value of cr0 register to eax register and output it to cr0 variable at the same time ret=cr0; cr0&=0xfffffffffffeffff;//Clear the 17th bit of the cr0 variable value and write the modified value to the cr0 register asm volatile("movq %%rax,%%cr0"::"a"(cr0));//Input the value of cr0 variable into register eax and move it to register cr0 at the same time return ret; } static void setback_cr0(int val) //Make the cr0 register non writable to the kernel { asm volatile("movq %%rax,%%cr0"::"a"(val)); } asmlinkage long sys_mycall(void) //Define your own system call { printk("Module system call-current pid: %d,current comm:%s\n",current->pid,current->comm); printk("hello,world!\n"); return current->pid; } static int __init call_init(void) { sys_call_table_my=(unsigned long*)(SYS_CALL_TABLE_ADDRESS); printk("call_init......\n"); anything_saved=(int(*)(void))(sys_call_table_my[NUM]);//Save system calls on the NUM location in the system call table orig_cr0=clear_cr0();//Make kernel address space writable sys_call_table_my[NUM]=(unsigned long) &sys_mycall;//Replace the system call on the NUM location with your own system call setback_cr0(orig_cr0);//Make kernel address space non writable return 0; } static void __exit call_exit(void) { printk("call_exit......\n"); orig_cr0=clear_cr0(); sys_call_table_my[NUM]=(unsigned long)anything_saved;//Recover system calls setback_cr0(orig_cr0); } module_init(call_init); module_exit(call_exit); MODULE_AUTHOR("25"); MODULE_VERSION("BETA 1.0"); MODULE_DESCRIPTION("a module for replace a syscall");
3. Preparation of makefile (M must be capitalized)
obj-m:=hello.o CURRENT_PATH:=$(shell pwd) LINUX_KERNEL_PATH:=/usr/src/linux-headers-4.15.0-46-generic all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
Enter the following commands in turn:
sudo make sudo insmod hello.ko lsmod //Check whether hello is inserted into the module
4. Write test c document
#include<stdio.h> #include<stdlib.h> #include<linux/kernel.h> #include<sys/syscall.h> #include<unistd.h> int main() { unsigned long x = 0; x = syscall(223); //Test system call 223 printf("Turing-1627405131 syscall result: %ld\n", x); return 0; }