例说linux内核与应用数据通信(一):添加一个系统调用

释放双眼,带上耳机,听听看~!

本文章以x86-32为例:


1
2
3
1$ uname -a
2Linux localhost 2.6.32 #1 SMP Sat Jun 13 23:55:06 CST 2015 i686 i686 i386 GNU/Linux
3

第一步,在系统调用表中加入一个表项,
表中为每一个有效的系统调用指定了惟一的系统调用号。系统调用表位于
arch/x86/kernel/syscall_table_32.S文件中,在该文件中最后一行添加自己的系统调用表项,如下:


1
2
3
4
5
6
7
1......
2        .long sys_preadv
3        .long sys_pwritev
4        .long sys_rt_tgsigqueueinfo     /* 335 */
5        .long sys_perf_event_open
6        .long sys_shallnet
7

虽然没有明确指定编号,但该系统调用已经按次序分配了337这个系统调用号,接下来就应该添加系统调用号。

第二步,添加系统调用号。
在Linux中,每个系统调用被赋予一个系统调用号。这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就被用来指明到底是要执行哪个系统调用。在文件
arch/sh/include/asm/unistd_32.h该列表中加入一行**#define __NR_shallnet   337 **


1
2
3
4
5
6
7
8
9
10
11
12
13
1......
2#define __NR_inotify_init1 332
3#define __NR_preadv 333
4#define __NR_pwritev 334
5#define __NR_rt_tgsigqueueinfo 335
6#define __NR_perf_event_open 336
7
8#define __NR_shallnet   337
9
10//#define NR_syscalls 337
11#define NR_syscalls 338
12......
13

在内核源文件中该行为#define NR_syscalls 337,在系统调用执行的过程中,system_call()函数会根据该值来对用户态进程的有效性进行检查。如果这个号大于或等于NR_syscalls,系统调用处理程序终止。所以应该将原来的#define NR_syscalls 337修改为#define NR_syscalls 338。

第三步,实现shallnet系统调用。在文件kernel/sys.c最后添加如下函数:


1
2
3
4
5
6
1SYSCALL_DEFINE0(shallnet)SYSCALL_DEFINE1(shallnet, int, arg)
2{
3        printk(KERN_ALERT"My blog address: \"http://blog.csdn.net/shallnet\"");
4        return arg + arg;
5}
6

第四步,重新编译内核。依次执行:


1
2
3
4
5
6
1make oldconfig
2make bzImage
3make modules
4make modules_install
5make install
6

第五步,重新启动系统然后进入刚新编译的系统,编写测试代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1#include <stdio.h>
2#include <unistd.h>
3#include <sys/syscall.h>
4
5#define __NR_shallnet 337
6
7int main(int argc, const char *argv[])
8{
9    int     ret;
10
11    ret = syscall(337, 99);
12
13    printf("shallnet() return: %d\n", ret);
14    return 0;
15}
16

编译执行该程序如下:


1
2
3
4
5
6
7
1$ ./target_bin
2shallnet() return: 198
3
4$ demsg
5......
6
7

可以看到我们新加的系统调用执行成功了。

可见建立一个新的系统调用还是很容易的,但是不提倡这么做,系统调用需要一个系统调用号,需要修改内核代码,修改之后需要重新编译内核。linux系统应当尽量避免每出现一个新的抽象就加入一个新的系统调用,通常有其他的方法可以代替系统调用,比如说实现一个设备节点等。

给TA打赏
共{{data.count}}人
人已打赏
安全运维

WordPress网站专用docker容器环境带Waf

2020-7-18 20:04:44

安全运维

运维安全-Gitlab管理员权限安全思考

2021-9-19 9:16:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索