接着“安全机制”、“安全模型”之后来看看“安全体系”。安全体系可以从系统的设计谈起,我们设计实现一个操作系统,必然要实现一些功能,满足必需的特定的要求,比如安全性、性能、可扩展性、容量、便捷、经济成本等,这些要求往往是有冲突的,因此为了将这些要求纳入到一个系统中并有效实现,通常都需要对于所有的需求进行全局性地折中考虑,使得系统在实现各项要求时目标明确,有轻重之分。而这项主要的任务就是由“安全体系”来完成的,可以说,就像建楼时的设计规划,设计操作系统的时候必须以安全体系作为指导。一般来说,安全体系主要包括以下四方面内容:
(1). 详细描述系统中安全相关的所有方面,包括系统提供的所有安全服务和保护系统自身安全的所有安全措施;
(2). 在一定抽象层次上描述各个安全相关模块之间的关系;
(3). 提出指导设计的基本原理;
(4). 提出开发过程的基本框架及对应于该框架体系的层次结构;
一般来说,安全体系结构又可以分为四类,分别是:抽象体系、通用体系、逻辑体系与特殊体系。逻辑体系与特殊体系的不同在于逻辑体系基于满足某项假设,不完全基于现实,因此不需要进行实现成本分析。安全体系的设计对于操作系统的实现十分重要,一般我们要遵循以下设计原则:
(1). 从系统设计之初就考虑安全性:如果设计时不考虑,后期添加将会付出巨大的时间经济成本,效果还未必理想;
(2). 应尽量考虑未来可能面临的安全需求:为将来可能的安全需求预留接口,安全需求指向应当具有方向性,不能太具体,丧失系统的灵活性;
(3). 隔离安全控制,并使其最小化;
(4). 实施特权最小化;
(5). 结构化安全相关功能;
(6). 安全相关界面友好;
(7). 不要让安全依赖于一些隐藏的东西:如不能基于以下假设-“用户不能突破系统,是因为用户没有用户手册或软件的资源列表”;
一、权能(capability)体系
权能,一般可以看成是对象的保护名,不同的系统使用权能的方法可能差异极大,但是权能都是具有如下的性质:
(1). 权能是客体在系统范围内使用的名字,在整个系统中都有效,而且在整个系统内唯一。
(2). 权能必须包含一部分用以决定该权能允许的对以它命名的客体的访问权;
(3). 权能只能由系统的底层部分创建,拥有某个权能的主体有权把它作为参数移动、拷贝或传递;
权能一般由以下部分组成:用于标识客体的标识符、定义客体类型的域及定义访问权的域。实现对权能的控制一般由两种方法,第一种是一直让权能存储在特殊的位置上,如权能段和权能寄存器,第二种方法是在每个存储字后加上一个额外的标签字段。权能机制虽然流行,但是却不能很好地适合提供策略的可变通性,因为它们允许权能的持有者控制这种权能的直接遗传,然而支持安全策略的重要要求时控制协调于策略的访问权遗传的能力
二、Flask体系
Flask体系的最大优势在于支持可变通的策略。互联网形式下的操作系统要求作为终端而言,足以支持大范围的可变通安全策略,然而操作系统中实现可变通的策略却比较棘手,表现在这种可变通性要求系统必须支持对底层客体的精细的访问控制,以便执行安全策略控制的高层功能;系统必须确保访问权限的增长和安全策略保持一致;策略在通常情况下不是固定不变的。为了解决策略的变化和支持动态策略,系统必须有一种机制来撤销以前授予的访问权限。Flask体系正是提出了吊销的机制。
Flask体系的策略可变通性主要借助于客体管理器和安全服务器共同实现,客体/对象管理器负责实施安全策略决策,而安全服务器提供对客体安全策略的仲裁。Flask体系安全结构为客体管理器提供了三个主要要素:(1)提供从一个安全服务器重新访问、标记和多实例决策的接口,多实例化决策规定多实例资源集的哪个成员被特定的请求访问;(2)提供一个访问向量缓存器(AVC)允许客体管理器缓存访问决策结果,减小性能消耗;(3)提供客体管理器接收和处理安全策略变动通知。
用户发起一个对于客体(文件、进程、网络等)的访问,首先客体管理器接收到请求,收集主体(用户)和客体的安全上下文(Context),并放松其SIDs给安全服务器,安全服务器负责对于请求进行仲裁。客体管理器再发送安全服务器之前首先检查自己的AVC中是否有类似的记录,若有直接返回;没有匹配才会联系安全服务器,安全服务器利用系统初始化建立的二进制策略做出仲裁,将结果写到AVC中,并且结果返回给客体管理器。这里的SID可以理解成是安全上下文的一个映射,安全上下文是一个可变长字符串,而SID则是一个长度固定的整数。
三、LSM框架体系
上面的内容对自己来说都比较抽象,这里相比就熟悉多了。下面简单介绍一下LSM。
LSM诞生背景
Linux内核只是提供了自主访问控制,缺乏对增强访问控制机制的直接支持,由于Linux支持动态加载核心模块的机制比较成熟,所以从原理上讲,增强的访问控制模块可以作为Linux核心安全模块来实现,实现灵活的动态加载从而支持安全策略的多样性。然而安全模块的有效创建却存在一些问题,因为和核心并不提供任何基础框架来允许核心模块仲裁对核心客体的访问,因此,核心模块典型地要借助系统调用来控制核心操作,而这样做方法严重受限;另外这些核心模块经常需要重构所选的核心功能,或者需要给核心打补丁,以支持模块。因此很多项目对Linux内核实现增强访问控制框架和模块都是以核心补丁的形式实现的。
SELinux出现之后,Linus Torvalds本人指导开发了LSM项目(Linux Security Module),LSM为主流Linux核心开发了一个轻量级的,通用目的的访问控制框架,使得很多不同的访问控制模型可以作为可加载的安全模块来实现。LSM具有如下三个特征:
(1). 真正通用,不同的安全模型的实施仅仅是加载不同的安全模块;
(2). 概念上简单,最小的扩散、有效;
(3). 能够作为一个可选安全模块,支持现有的POSIX.1e权能逻辑;
LSM的实现机制
LSM主要添加了两个机制,一个是在核心数据结构中增加了安全域(void * security),在核心代码中管理安全域;另一个是在实现访问控制的关键点插入对“安全钩函数(hook)”的调用。它也增加了注册和注销安全模块的函数,增加了通用的security系统调用,来实现对安全相关应用的支持。访问控制的关键点的左右在于仲裁对核心内部客体的访问。LSM试图来回答如下问题:”一个主体S可以对核心内部客体O执行核心操作OP吗?”,即(S, O, OP)问题。
LSM框架利用核心现有机制来讲用户空间的数据转化成内核空间数据结构,使得LSM框架能够在核心实际实施所请求之前,存取到完整的核心上下文,直接仲裁对核心数据结构的访问。小结一下LSM所有的实现方法:
(1). 在特定的内核数据结构中加入安全域;
(2). 在内核代码中的管理域和实现访问控制的关键点插入对钩子函数的调用;
(3). 加入一个通用的安全系统调用;
(4). 提供函数允许内核模块注册为安全模块或者注销一个安全模块;
(5). 将大部分权能逻辑移植为一个可选的安全模块;