首页 理论教育 Linux内核安全模块详解:内核中的虚拟机

Linux内核安全模块详解:内核中的虚拟机

时间:2023-11-22 理论教育 版权反馈
【摘要】:在多个扩展方案中,BPF方案胜出。len表示后边数组insns的长度。在引入seccomp的filter模式之前,内核中已经有用于网络包过滤的sock_filter,seccomp的filter模式利用了现成的机制:sock_filter规定了一种指令结构,有代码、跳转和立即数。这种指令运行在一个虚拟的计算机上,称为BPF虚拟机。存储指令将累加器或索引寄存器中的数据存入内存。网络包过滤的相关代码提供了使用JIT编译后指令的逻辑,在本书参考的内核版本3.14-rc4中,seccomp没有这样,还是老老实实地调用解释执行的sk_run_filter函数。

Linux内核安全模块详解:内核中的虚拟机

secomp的strict模式的优点是简单,限制得也很彻底。它的缺点是:

(1)允许的系统调用太少。

(2)不能对系统调用的参数进行限制,比如只允许write标准输出而不允许write其他文件。

在seccomp的后续开发中,出现了几个扩展方案。在多个扩展方案中,BPF方案胜出。BPF是Berkeley Packet Filter的缩写。此方案增加了一个模式:SECCOMP_MODE_FILTER,并在结构体seccomp中增加了一个类型为seccomp_filter的成员filter。

下面看一下seccomp_filter:

usage是一个引用计数。prev用于将filter串成链表。len表示后边数组insns的长度。数组insns存储的是filter指令。因为seccomp规定filter一旦建立就不允许修改,包括添加新的filter指令,所以后续要增加新的filter指令时,就要建立一个新的类型为seccomp_filter的filter实例,用其成员prev将旧的filter串起来。

关键数据结构是sock_filter,用于网络系统的过滤。在引入seccomp的filter模式之前,内核中已经有用于网络包过滤的sock_filter,seccomp的filter模式利用了现成的机制:

sock_filter规定了一种指令结构,有代码、跳转和立即数。这种指令运行在一个虚拟的计算机上,称为BPF虚拟机。这个BPF虚拟机有一个累加器(accumulator),一个索引寄存器(index register),大小为16×32bit的内存(Scratch Memory Store)和一个不可见的程序计数器(program counter)。说它是虚拟机,不如说它是伪机(Pseudo Machine),因为它的某些指令要取网络包头或者系统调用号之类的数据,这些东西不在它那可怜的16×32bit内存中。不管怎么说,这种指令系统十分简单,通过它可以比较容易地定义过滤条件。下面介绍一下指令系统。

(1)加载指令

将数据加载到累加器或索引寄存器。数据来源可以是立即数(sock_filter结构体中的k)、网络包、网络包长度、内存(Scratch Memory Store)、系统调用号、系统调用的参数等。

(2)存储指令

将累加器或索引寄存器中的数据存入内存(Scratch Memory Store)。(www.xing528.com)

(3)算术和逻辑指令

对累加器中的数据执行算术或逻辑运算,运算结果存回累加器,运算参数来自索引寄存器或立即数。

(4)跳转指令

基于累加器中数值和索引寄存器中数值的比较结果,或者基于累加器中数值和立即数的比较结果,改变指令控制流。

(5)返回指令

结束处理,返回状态。

(6)其他指令

目前包含两条指令,一条用于将索引寄存器的值存入累加器,另一条用于将累加器的值存入索引寄存器。

内核执行BPF指令的代码在net/core/filter.c的sk_run_filter函数中。它是解释执行的,读一条指令,根据语义执行相应的操作。有趣的是,内核开发者引入了JIT(Just In Time)编译器,将BPF指令编译为本机指令,提高运行速度。网络包过滤的相关代码提供了使用JIT编译后指令的逻辑,在本书参考的内核版本3.14-rc4中,seccomp没有这样,还是老老实实地调用解释执行的sk_run_filter函数。

另外,为了生成BPF指令,也有些用户态工具提供编译和汇编功能,例如netsniff-ng [5] 软件包中的bpfc。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈