杜军龙,周剑涛
(江西省信息中心,南昌 330001)
强制性访问控制(Mandatory Access Control,MAC)[1]被美国国家计算机安全中心NCSC的安全标准TCSEC列为B级安全操作系统的基本要求[2]。MAC具有非常强的鲁棒性,能够绝对执行安全管理员预定的访问控制策略,有效防止特洛伊木马的攻击。目前对Linux操作系统平台的MAC机制研究较多且侧重点不同,主要研究包括Flask模型、Clark-Wilson模型、Bell-lapadula模型、Biba模型、Chinese-Wall模型、DTE模型和Lattice模型以及各企业、团体自主研发的设计模型等[3-6]。
然而,在特殊单位中,单一MAC机制很难完全满足其通用Linux平台使用的特殊性与多样性安全需求,需要多种MAC机制并存互补,以提供更高的系统安全性。目前针对通用Linux系统中的多MAC机制并存研究较少,以Selinux机制为代表的具有主/从性的多MAC堆叠并存机制较为普及,它将Selinux作为主安全模块,后续MAC机制通过mod_reg_security函数在主模块中进行注册成为从安全模块,较好地支持了MAC并存与调用,但从安全模块受主安全模块策略的约束与管理,并且在kernel-2.6.19以后不支持mod_reg_security函数的使用[7]。文献[8]设计了一种在kernel源码中以安全域数组的形式实现的多MAC机制并存管理器,有效地支持了多MAC并存,但这种并存管理器的平台可迁移性差,对于不愿更改内核的用户,他们难以接受这种方法。文献[9]利用扩展内核hook安全域的形式,以内核通用链表做载体为系统提供一种多MAC并存机制,但是该法的综合决策和链式调用存在系统开销大和灵活性不足问题。
基于以上问题,在沿袭内核hook安全域扩展的基础上,本文提出一种多种MAC机制并存的动态装载方法。该方法使MAC机制以动态方式载入系统且能与平台自有MAC机制实现并存,同时辅以优先级调度算法实现灵活调度[10]。
目前, Linux操作系统平台自带的通用MAC机制大都是依托Flask模型进行工程实现的[11]。Flask模型以进程为主体,按照集中式或分散式的策略权限访问系统资源客体,存在类型强制与多层安全非强制的形式,同时具备控制精细、策略灵活与可配置等特点。通用MAC机制通过更改内核全局描述表security_ops中hook地址指向,以KO的形式进行动态装载[12]。通用MAC装载及其控制流程如图1所示。
图1 通用MAC装载流程
通用MAC装载流程主要包括以下步骤:
1)系统开机,内核层首先进行安全初始化,将内核全局描述表security_ops地址指向系统默认安全模块default_security_ops,此过程无任何MAC机制,仅作为初始化使用。
2)平台自带Flask模型的MAC机制将获取内核全局描述表security_ops地址,并进行地址替换,使之指向MAC机制中自定义的全局描述表,此时系统平台的初始化安全模块default_security_ops失效,MAC机制装载成功且生效。
3)用户层进程访问客体,首先读取系统文件目录项,查找系统资源客体inode节点,并获取inode节点属性信息,然后经过内核接口执行程序功能性错误检查。
4)进行系统平台传统的DAC权限检查校验。
5)经过以上步骤,在用户进程即将访问客体之前,内核层生效的MAC机制将读取强访策略,最终确定主体访问客体权限。
系统内核中的透明安全域是一个void*类型指针,它将安全模块中的安全信息和内核内部对象联系起来,对MAC机制的支持具有唯一性,如若安全域被主模块占用,势必导致其他MAC机制失效。针对要实现2种甚至多种MAC机制的并存问题,本节对多种MAC机制并存动态装载进行设计与实现。
针对Linux平台需要多种MAC机制并存以增强系统安全性的需求,提出一种具备灵活调度的多种MAC机制并存动态装载方法。该方法主要分为MAC机制装载与还原、并存调度策略、访问仲裁和安全防篡改4个部分,其设计装载流程如图2所示,其中,header为跳跃表头。
图2 MAC并存装载流程
多种MAC机制并存装载沿袭了内核安全域扩展思想,但在安全模块加载过程与传统通用动态装载的hook地址替换法不同,它利用跳跃表[13]对内核全局描述表security_ops的入口点进行重新构造,以实现多MAC装载管理机制与MAC模块功能的静态分离。跳跃表装载多MAC的机制作为与MAC功能模块交互的唯一途径,具有顺链式(先进先出的MAC互联逻辑)与跳跃式(任意顺序的MAC互联逻辑)2种调用,如图2所示。鉴于系统安全的第一要义是安全,其次是性能,管理机制可无上限装载多个MAC有违系统安全和性能要求,将MAC装载上限以可配置的方式予以提供。多种MAC机制还原是对跳跃表装载方式移除后的环境归整,还原为系统平台自带MAC的强访境况。
并存调度策略摒弃了以往FIFO模型实现的链式顺序调度思想,利用优先级算法实现了多MAC机制的并存灵活调度设计。优先级P是根据实际中不同MAC机制的侧重点不同进行的静态标签设置,如图2所示。预定义P为8个等级,P={P0,P1,…,P7},P0优先级最高,依次逐级递减,同等优先级时,按照先进先出顺序进行调度。
访问仲裁是多MAC机制并存策略最终的决策者,决定了策略最终实施的成功与否。在已有并存技术中,全部MAC机制运行后对返回结果做统一仲裁的方式具有可行性,但却要将系统已装载的MAC都运行。简单说,如果系统中第一个MAC机制已确认该操作不安全,下面的MAC机制则不需要运行实施,可直接给出仲裁结果。鉴于不同MAC机制具体的权威性与可信性不同,如若直接给出仲裁结果,可能导致仲裁偏差与失误,本文设计的访问仲裁通过引进权重比W的方式对结果进行修正,以增添仲裁可信性。W可设置为W={W0,W1,…,Wn},权重值越大,则影响力越大[14],如图2所示。
安全防篡改功能是MAC机制并存方法在系统中的自安全增强机制,具备防篡改监控和自修复2个特点,如图2所示。防篡改监控包含监控时间片和地址判断2个要素。自修复是在防篡改监控发现被篡改的情景下做出的并存机制重载修复操作。
假设存在以下条件:
1)需并存装载的MAC机制集合M={M0,M1,…,M6}。
2)已定义优先级P为8个等级,P={P0,P1,…,P7}。
3)已定义权重W为3个等级,W={W0,W1,W2}。
多种MAC机制并存动态装载设计的实现过程如下:
1) MAC并存装载与还原
内核安全域已被系统中自带MAC机制占用,首先将安全域以SkipList形式进行扩展,以支持多安全模块的注册,以file结构的安全域void *f_security为例进行扩展,扩展前为struct file{…void*f_security;…},扩展后则为struct file {…struct mskiplist *list;void*f_security;…}。
file结构安全域扩展后的调用原理如图3所示。file结构的安全域由之前指向系统自带MAC机制的file结构,更改为指向SkipList的头节点,SkipList中的各个节点安全域指针被设置指向具体安全模块的file结构。
MAC并存装载要对系统内核全局描述表security_ops的地址进行备份与替换,然而在通用Linux内核2.6.22及以上版本[15]中,已经不支持通过register_security函数操作security_ops地址方式,需手动进行获取,其关键数据结构实现如下所示:
static int __coexit_init(void)
{static struct security_operations sec_ops_bak;
memset(&sec_ops_bak,0,sizeof(sec_ops_bak));
sec_ops_p = look_up_symbol("security_ops");
…;
memcpy(&sec_ops_bak,sec_ops_p,sizeof(sec_ops_bak));
…}
其中,第1行和第2行是为security_ops备份地址申请空间并初始化,第3行和第4行将获取的security_ops地址进行备份。
多MAC装载需维护一个安全模块函数链表,该链表以跳跃表的数据结构实现,其节点结构如下所示:
typedef struct skiplist_node{
int p; /*优先级*/
float w; /*权重*/
int levels; /*保存结点的层数*/
struct security_operations * security_ops;
/*MAC机制中hook函数表*/
struct skiplist_node_level{
struct skiplist_node *forward; /*前指针*/
}level[]; /*level最大值为32*/
struct skiplist_node *backward; /*后指针*/
}skiplist_node;
将所需并存的MAC机制M={M0,M1,…,M6}装载在安全模块函数链表中,其示意图如图4所示。
图4 多MAC并存装载示意图
2) MAC并存调度
并存调度策略引入了优先级调度算法思想,MAC的优先级P以静态标签形式存在。已知集合M,设M与P的自由组合为{M0,P0}、{M1,P7}、{M2,P2}、{M3,P0}、{M4,P1}、{M5,P1}和{M6,P0},如图5所示。根据优先级高先调用、同等级按照先进先出的调度原则,MAC并存调度机制首先调用的是优先级最高的P0级,调用顺序为{M0,P0}、{M3,P0}和{M6,P0},如图5中所标线(长虚曲线)所示;然后,调用的是{M4,P1}和{M5,P1},如图5中所标线(短虚曲线)所示;最后,调用的是{M2,P2},如图5中所标线(实曲线)所示。
图5 MAC调度示意图
3) 访问仲裁
访问仲裁中处理的对象包含MAC集合M={M0,M1,…,M6},权重W={W0,W1,W2},K表示计算结果动态修正系数,R表示当前模块返回结果,Z表示最后计算结果,以Ψ表示访问仲裁集合,Ψ={M,W,K,R,Z}。
(1) MAC机制集合M={M0,M1,…,M6},按照优先级P的顺序依次执行,并对应返回结果R={R0,R1,…,Rn}。
(2)结果集R结合模块权重W和修正系数K进行决策计算,得出仲裁结果Z={undef,Z1,Z2,…,Zn}。其计算公式为:
(1)
4) 安全防篡改
安全防篡改中的篡改监控特征是通过周期轮巡的方式进行实现,通过比对security_ops的入口地址是否被跳跃表以外的地址进行替换而做出篡改判断依据,其时间片可设置为3 s,如若被非法篡改,自修复特征将重新获取security_ops的入口地址主动权,将多MAC机制重新装载入系统。
本文将该并存方法在Linux通用系统平台中进行了实现,主要的系统性能验证如下:
1) 系统功耗性验证
测试条件:
(1)系统中已默认装载Flask模型实现的MAC机制。
(2)设存在系统MAC补充机制M0和M1,并且M0和M1中的功能hook均返回0,用以忽略hook函数内部的功能影响,以代表访问过程均安全放行。
在Linux平台条件(1)和(2)的环境下,实验对比了多MAC机制堆叠并存装载方法[7]和本文设计的多MAC机制并行装载方法,分别执行10 000次、100 000次和1 000 000次的文件打开与关闭,并记录执行所用时间,每一组重复执行10次,然后取其平均值。2组实验结果对比如图6所示。
图6 通用堆叠与并行装载执行时间对比
2) 防篡改功能验证
假设在Linux通用系统平台中已安装本文可支持的多种MAC并存动态装载机制,同时该并存动态装载机制中包含系统自带MAC及其补充MAC机制M0和M1。参照系统syslog审计方式,在并存动态装载机制中每隔一定时间片主动获取系统时间与内核全局描述表security_ops地址,并通过vfs_write函数将相关信息记录到/var/log/security_ops.log中。
在Linux通用系统平台中,创建文件replace_security_ops.c用以强占并更改security_ops指向地址。在文件replace_security_ops.c中,首先获取当前系统内核全局描述表security_ops指向地址,然后更改security_ops指向地址,最终将文件以KO模块形式编译生成lsm.ko,通过执行insmod命令,将lsm.ko插入内核,如图7所示。
图7 安全防篡改测试截图
在日志/var/log/security_ops.log中,每隔3 s输出当前security_ops指向地址,在insmod操作动作执行前,系统输出提示信息的INFO语句,显示security_ops地址为ffffffff81ae2420。当执行insmod操作动作后,系统输出提示信息WARN语句,显示系统security_ops地址已被篡改,且篡改后地址为ffffffff81fdadc8。此时安全防篡改模块将执行自修复功能,重新主动占据security_ops指向地址。经上述security_ops强占测试后,最终确认此方法具备安全防篡改功能。
本文提出一个多MAC机制并存的动态装载方法,在并存装载的同时以优先级调度算法对其进行灵活调度。测试结果表明,相比于通用堆叠并存技术,该方法能够满足多种MAC机制的系统并存需求,系统性能开销小,并且模块具备安全防篡改功能。下一步将对并存方法中的各种MAC机制运行时间片进行研究,在考虑优先级的情况下同时考虑时间要素,以先调用同优先级、时间片较小的MAC机制的方式达到更优的调度方案,进而提高系统性能。