8.4 扩展属性简单是有代价的相比于 SELinux 只用到一个扩展属性“security.selinux” SMACK 用到的扩展属性非常多。原因是 SMACK 的策略过于简单了简单的策略难以应付复杂的系统。为了应对层出不穷的挑战 SMACK 引入了多个扩展属性1 SMACK64这是最基本的扩展属性文件客体的安全标签来自此属性。2 SMACK64EXEC当进程执 行 exec 系统调用时 进程的新安 全标签来自 被执行文件 的“ security. SMACK64EXEC”属性。3 SMACK64TRANSMUTE这个属性作用于目录当其值为“TRUE”时在此目录下新建的文件/目录的安全标签扩展属性 SMACK64值来自此目录的安全标签扩展属性 SMACK64。4 SMACK64MMAP这个扩展属性针对的是共享库shared library。通过这个标签为文件赋予了一个新的安全标签——作为共享库的安全标签。当进程通过 mmap 系统调用载入共享库文件时文件的共享库标签不能拥有超越进程标签的操作许可。举个例子进程标签为 normal一个共享库文件的共享库标签为 high。进程要访问的一个文件的标签为 secret。系统策略为normal secret wa high secret rwa当进程加载共享库时就会失败因为共享库 high 对 secret 的操作许可 rwa 超越了进程对“secret”的操作许可 wa。SMACK 的这种设计不好理解而且有两个潜在的问题。首先文件成了某种意义上的主体这在理论上不好解释其次 mmap 系统调用不止用于加载共享库文件。5 SMACK64IPIN6 SMACK64IPOUT这两个扩展属性是套接字专有的扩展属性 SMACK64IPIN 用于访问控制比如判断当前进程能不能发送数据包到某个套接字。 SMACK64IPOUT 用于给发出的包packet 赋安全标签。8.5 伪文件系统SMACK 利用伪文件系统作为用户态应用和内核的接口。 SMACK 也用到了/proc/[pid]/attr目录下的文件不过它只允许操作其中一个文件 current。除此之外 SMACK 还自创了一个名为 smackfs 的文件系统。文件系统 smackfs 中的文件按照功能可以分为两类一类和策略相关另一类和网络标签相关。8.5.1 策略相关文件1 loadSMACK 访问控制的核心是策略。策略有两部分一部分是所谓的系统策略是不可更改的另一部分是用户可配置的策略。下面首先简单介绍一下系统策略。SMACK 预先定义了 5 个标签 ?、 ^、 *、 _和见表 8-1。SMACK 预先定义了以下 7 条策略1标签为“*”的主体进程不能对任何客体进行任何操作。2标签为“^”的主体进程可以对任何客体进行读r或执行x操作。3任何主体进程可以对标签为“_”的客体进行读r或执行x操作。4任何主体进程可以对标签为“*”的客体进行任何操作。5任何主体进程可以对标签相同的客体进行任何操作。6用户定义的策略所允许的操作都被允许。7其他操作都不被允许。文件 load 是用来存取用户定义的策略的接口。 对此文件的写操作的要求是 一次写入一行每行的格式是%24s%24s%5s第一个字符串表示主体安全标签第二个字符串表示客体安全标签第三个字符串是操作方式全部操作方式是“rwxatl”表示读、写、执行、添加、变形、锁。如果相应的操作不被允许就在相应的位置上填“-”。2 load-self这个文件提供了一个接口用来为进程提供额外的访问控制策略。与很多安全机制一样通过这个接口只能减少允许的操作。3 logging这个文件接口用于控制 SMACK 的日志策略记录失败、记录成功、都记录、都不记录。这个文件的内容是一个整数。代码实现是/** logging functions*/#define SMACK_AUDIT_DENIED 0x1#define SMACK_AUDIT_ACCEPT 0x2extern int log_policy;变量 log_policy 的比特位 0 对应是否记录失败事件比特位 1 对应是否记录成功事件。4 access这个伪文件接口用于检查规则的合法性。向这个文件写入一条规则比如secret normal rw然后再读取文件内容如果内容是 ascii 字符‘1’则前面写入的规则被内核允许如果是 ascii字符‘0’则前面写入的规则不被内核允许。5 onlycap简单是有代价的 SMACK 策略中的存取方式没有覆盖的东西太多了比如什么情况下可以修改安全策略。 SMACK 策略中客体也有缺失比如安全策略本身是不是客体它的标签又是什么为了解决这些问题 SMACK 的方式是引入超级标签拥有超级标签的主体可以做诸如修改策略这样的特殊工作。在 Linux 能力机制中有两个能力 CAP_MAC_ADMIN 和 CAP_MAC_OVERRIDE。CAP_MAC_ADMIN 的 语 义 是 拥 有 它 可 以 对 强 制 访 问 控 制 MAC 进 行 管 理 CAP_MAC_OVERRIDE 的语义是拥有它可以不受强制访问控制机制的限制。这两个能力的引入有些不合逻辑能力机制本质上属于自主访问控制DAC DAC 不应该超越 MAC。SMACK 的问题是机制过于简单它需要引入一个类似于超级用户的角色来弥补机制的不足。 SMACK 引入了一个特殊的标签 smack_onlycap。 让这个标签和前述两个能力配合起来工作。具备 smack_onlycap 标签的进程 如果拥有了 CAP_MAC_ADMIN 能力 它就可以进行 SMACK策略管理工作。具备 smack_onlycap 标签的进程如果拥有了 CAP_MAC_OVERRIDE 能力就不受 SMACK 限制。onlycap 文件提供对 smack_onlycap 标签进行管理的接口写标签字符串可以修改smack_onlycap 值写入“ -”清空 smack_onlycap。若 smack_onlycap 为空进程只要拥有CAP_MAC_ADMIN 就可以进行 SMACK 策略管理工作只要拥有 CAP_MAC_OVERRIDE 就可以不受 SMACK 限制。6 revoke-subject通过这个文件接口写入一个标签系统中具备这个标签的进程对所有客体都无法进行任何存取操作。7 change-rule通过这个文件接口对系统现存策略进行修改。格式为%s %s %s %s前两个字符串分别是主体标签和客体标签第三个字符串是允许的操作第四个字符串是不允许的操作。如果要修改的策略不存在就创建新的策略。8 syslogsyslog 文件用来修改和查看变量 smack_syslog_label。这个变量标示一个特殊的标签拥有这个标签可以进行 syslog 相关的操作。8.5.2 网络标签相关文件1 ambient这个文件反映的是无标签网络包的安全标签。 SMACK 依靠 IP 协议中一个未能成为标准的选项 CIPSO㊀ 来将安全标签附着于 IP 包包头之中。这就带来一个小问题当收到一个没有CIPSO 数据的 IP 包时此 IP 包的安全标签是什么呢总得有什么方式来规定缺省值吧。这个缺省值的规定接口就是这个 ambient 文件。 ambient 文件的内容是一个字符串规定了网络包的缺省标签。2 cipsoCIPSO 的标准㊁ 规定网络数据包携带敏感级别和敏感类别敏感级别是一个整数敏感类别是一个整数的集合。看起来 CIPSO 中敏感级别和敏感类别的设计来自 Bell-Lapadula 模型。而 SMACK 安全标签是一个字符串。这就需要用一种方式将二者联系起来。 cipso 文件就是做这件事的。先说对 cipso 文件的写操作一次写入一行每行的格式是%24s%4d%4d[%4d]...第一个参数是字符串表示 SMACK 安全标签第二个参数是整数为 CIPSO 的敏感级别值第三个参数是整数表示后续还有几个整数这些整数是 CIPSO 的敏感类别值。举个例子level-3-cats-5-19 3 2 5 193 direct上面的 cipso 文件只是沟通 cipso 标签和 SMACK 标签的一座桥 如果它是唯一的映射方式那么为每一个 cipso 标签和 SMACK 标签都做出规定是一件很麻烦的事。在 SMACK 系统中还有更加直接的方式。前面提到 CIPSO 标签包含级别和类别级别是一个整数类别是整数的集合。在实际的网络包中每个类别是一个比特整个类别的集合就是一个字符串。 SMACK 就直接用这个字符串来携带 SMACK 安全标签因为 SMACK 标签也是一个字符串。不过这就完美了吗且慢还有一个问题承载类别集合的这个字符串有长度限制。看看 SMACK 代码中这段注释* * Maximum number of bytes for the levels in a CIPSO IP option. * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is * bigger than can be used, and 24 is the next lower multiple * of 8, and there are too many issues if there isnt space set * aside for the terminating null byte. */ #define SMK_CIPSOLEN 24cipso 限制级别字符串的长度上限是 30 SMACK 进一步限制可用其中的开始 24 个字节。当 SMACK 安全标签字符串长度低于 24 时 直接将 SMACK 安全标签放入 cipso 级别字符串中。当 SMACK 安全标签字符串长度等于或大于 24 时将 SMACK 安全标签转化为一个整数smk_secid然后将 smk_secid 放入 cipso 类别字符串。为区分这两种情况前一种情况下 cipso级别值为 smack_cipso_direct后一种情况下 cipso 级别值为 smack_cipso_mapped。direct 文件就是为了存取变量 smack_cipso_direct 而出现的。4 mapped此文件用于存取变量 smack_cipso_mapped。5 doicipso 标准考虑到级别和类别的地域性问题 即级别和类别在一组网络节点中的含义与在另一组网络节点中的含义是不同的。为了区分地域 cipso 标准规定 ip 的 cipso 选项中还应携带另一个信息 doi全称是 domain of interpretation。smackfs 的 doi 文件用来读写 doi 的值。6 netlabelcipso 选项并没有成为正式标准大多数系统没有实现它。实现了 cipso 的网络节点如何与不支持 cipso 的网络节点交互呢首先在这两个节点间交互的 IP 网络包不要带 cipso其次可以认为全部来自或发往不支持 cipso 网络节点的 ip 网络包都带有同一个安全标签。文件 netlabel 就是用来规定来自某个或某些网络节点的网络包的网络标签。文件每一行的格式如下%d.%d.%d.%d label 或者 %d.%d.%d.%d/%d label 前面的格式用于单个网络节点后面的格式用于子网。举个例子 172.16.1.100 file-server 192.168.1.1/24 internal-subnet8.5.3 其他文件下面要介绍一些功能和上面介绍的文件相同的文件这些文件不同的只是输入的形式。● access2● cipso2● load2● load-self2这些带“2”的文件接口和前面不带“2”的文件接口功能相同只是输入格式有变。前面的文件接口要求标签的输入固定为 24 个字符不够的补空格长度不能超过 24。这里没有这个限制短了就少写长了就多写。读到这里你还觉得 SMACK 简单吗8.6 网络标签通读 SMACK 代码你会发现有关网络标签netlabel的代码占了很大部分。网络标签背后的标准是一个很早就提出但一直没有成为标准的 IETF draft㊀ ——CIPSO Commercial IP Security Option。大致上这个标准草案就是利用 IP 包头的 option 空间携带一些安全信息安全信息包括“敏感级别”和“敏感类别”。这个标准草案写于 1992 年二十多年过去了它还是草案。问题在哪里呢作者认为它的问题主要有两个1它规定携带的安全信息是“敏感级别”和“敏感类别”这很明显是 Bell-Lapadula 模型的产物而 Bell-Lapadula 模型产生于 20 世纪 60 年代末 70 年代初它的应用领域有些窄。2它对安全信息本身没有相应的保护这意味着在网络环境中任何一台计算机都有可能伪造自己发出的 IP 数据包的“敏感级别”和“敏感类别”信息。接收方无法验证接收到的网络包的“敏感级别”和“敏感类别”的正确性。SMACK 使用了 CIPSO。对于第一个问题 SMACK 在实现中在自己的安全标签和 CIPSO标签间建立了一一对应的映射关系可以认为 SMACK 对“敏感级别”和“敏感类别”进行了转义。对于第二个问题 SMACK 没有做任何事只是假设在一个可信的安全的网络环境中使用 CIPSO 标签。8.7 总结SMACK 是打着“简单”的大旗杀入 Linux 的。分析其代码我们发现它的简单主要体现在三个地方首先是它将主体对客体的访问方式简化了只有读、写、执行、增加等几种其次是它将对自身的访问控制即作为安全机制的承载基础的标签和策略排除出体系将之委托于特权最后是预制了若干标签和策略在不自己定义标签和策略的情况下用户也可以使用SMACK 功能。SMACK 的主要应用领域是嵌入式系统。但是最主流的嵌入式系统 Android 并没有使用它。8.8 参考资料读者可参考 Documentation/security/Smack.txt。习题smackfs 中有一个文件 syslog其内容是一个 SMACK 标签。拥有此标签的进程可以进行哪些 syslog 相关的操作为什么 SMACK 要这么设计如果不这么设计还有什么别的方式