Two methods of adding system call under Linux(Ubuntu) (kernel compilation method module addition)

Posted by derrick1123 on Sat, 30 Nov 2019 12:19:12 +0100

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;
}

 

Topics: Linux sudo Makefile shell