VMware中Ubuntu添加系统调用

VMWare中Ubuntu添加系统调用

向linux添加系统调用,一种方式是编译内核添加,二种方式是通过内核模块的方式添加。
对于第一种通过编译内核方式添加系统调用,比较耗时。一般在普通pc机中编译内核一般在3个小时左右,而且这还是在你添加系统调用没有语法错误的情况下。其次编译内核要保证 Ubuntu 内存在30G 左右,昨天我就是通过编译内核添加,但是在我等3个半小时后,编译通过了但是在内核安装的时候却出现了问题,显示硬盘不足我在虚拟机安装Ubuntu 时默认分配20G 内存(我的内心几乎是崩溃的),结果第一种方法我就放弃了。
开始了我第二种方法,通过内核模块添加。
首先说明一下我的系统环境

  • VMware 版本是14.0

    Vmware版本

  • Ubuntu 版本是 64位的18.04

环境准备好,那就开干吧

首先我是参考了下面这个链接,写的该篇博客,感谢大佬

https://www.cnblogs.com/wangliangblog/p/9234463.html

1.查看预留系统调用号
首先我在Google 搜索了好多篇文章介绍怎么查看Ubuntu 预留的系统调用号,结果却怎么也找不到。下面我告诉大家怎么查询系统调用号。

  • 在/usr/src/linux-headers-4.15.0-29/ 通过搜索找到 unistd_64.h
    如果你是32位的系统,你找的文件就应该是unistd_32.h.
    VMware中Ubuntu添加系统调用_第1张图片

  • 打开这个文件继续搜索 unused 你就是发现系统预留的调用号是 251
    VMware中Ubuntu添加系统调用_第2张图片

  • 获取系统调用表sys_call_table 的地址

  • 通过 cat /proc/kallsyms | grep sys_call_table 查看系统调用地址
    建议以root 用户登录查询。
    VMware中Ubuntu添加系统调用_第3张图片


  1. 编写模块modu.c
#include 
#include 
#include 
#include 
#include 
#include 

#define my_syscall_num 251
//如下的这个值要到你机子上查。cat /proc/kallsyms | grep sys_call_table
#define sys_call_table_adress 0xa4a001a0


unsigned int clear_and_return_cr0(void);
void setback_cr0(unsigned int val);
asmlinkage long sys_mycall(void);

int orig_cr0;
unsigned long *sys_call_table = 0;
static int (*anything_saved)(void);

unsigned int clear_and_return_cr0(void)
{
 unsigned int cr0 = 0;
 unsigned int ret;
 asm("movl %%cr0, %%eax":"=a"(cr0));
 ret = cr0;
 cr0 &= 0xfffeffff;
 asm("movl %%eax, %%cr0"::"a"(cr0));
 return ret;
}

void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中
{
 asm volatile("movl %%eax, %%cr0"::"a"(val));
}

static int __init init_addsyscall(void)
{
 printk("hello, kernel\n");
 sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址
 anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址
 orig_cr0 = clear_and_return_cr0();//设置cr0可更改
 sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址
 setback_cr0(orig_cr0);//设置为原始的只读cr0
 return 0;
}

asmlinkage long sys_mycall(void)
{
 printk("This is my_syscall!\n");
 return current->pid;
}

static void __exit exit_addsyscall(void)
{
 //设置cr0中对sys_call_table的更改权限。
 orig_cr0 = clear_and_return_cr0();//设置cr0可更改

 //恢复原有的中断向量表中的函数指针的值。
 sys_call_table[my_syscall_num] = (unsigned long)anything_saved;
 
 //恢复原有的cr0的值
 setback_cr0(orig_cr0);

 printk("call exit \n");
}

module_init(init_addsyscall);
module_exit(exit_addsyscall);
MODULE_LICENSE("GPL");

  • 编写Makefile 文件
    Makefile文件的编写可以参考一些其他博客,基本上都是差不太多。

你可能感兴趣的:(Linux内核,Ubuntu,系统调用,模块编写)