VMWare中Ubuntu添加系统调用
向linux添加系统调用,一种方式是编译内核添加,二种方式是通过内核模块的方式添加。
对于第一种通过编译内核方式添加系统调用,比较耗时。一般在普通pc机中编译内核一般在3个小时左右,而且这还是在你添加系统调用没有语法错误的情况下。其次编译内核要保证 Ubuntu 内存在30G 左右,昨天我就是通过编译内核添加,但是在我等3个半小时后,编译通过了但是在内核安装的时候却出现了问题,显示硬盘不足我在虚拟机安装Ubuntu 时默认分配20G 内存(我的内心几乎是崩溃的),结果第一种方法我就放弃了。
开始了我第二种方法,通过内核模块添加。
首先说明一下我的系统环境
-
VMware 版本是14.0
-
Ubuntu 版本是 64位的18.04
环境准备好,那就开干吧
首先我是参考了下面这个链接,写的该篇博客,感谢大佬
1.查看预留系统调用号
首先我在Google 搜索了好多篇文章介绍怎么查看Ubuntu 预留的系统调用号,结果却怎么也找不到。下面我告诉大家怎么查询系统调用号。
-
在/usr/src/linux-headers-4.15.0-29/ 通过搜索找到 unistd_64.h
如果你是32位的系统,你找的文件就应该是unistd_32.h.
-
打开这个文件继续搜索 unused 你就是发现系统预留的调用号是 251
-
获取系统调用表sys_call_table 的地址
-
通过 cat /proc/kallsyms | grep sys_call_table 查看系统调用地址
建议以root 用户登录查询。
- 编写模块modu.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/unistd_64.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#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文件的编写可以参考一些其他博客,基本上都是差不太多。