SELinux 在 Fedora 中策略的实现

从 Fedora Core 3 开始,SELinux的策略数据存储于/etc/security/selinux/X/src/policy/目录下(X指你选则的策略,可以是 “strict” 或者 “targeted”)。在这个目录中,你可以使用"make load"来编译并装在策略。也就是用那个命令将策略编译成二进制格式并装在到内核中,并立即生效。除了装如内核,该命令还将策略的二进制格式存储到 /etc/selinux/X/policy/policy.YY文件中,这里X指你选则的策略,可以是"strict" 或者 “targeted”,YY是策略的版本号(Fedora Core 3支持最新的版本是18)。这是为了在系统开机的第一时间,init可以迅速装载策略到内核。/etc/selinux/config这个配置文件用来告诉init那些策略需要装载。

当你启动一个SELinux时,init所做的第一件事就是挂载/proc文件系统,并判断SELinux是否被激活。init通过selinuxfs文件系统类型来判断内核中是否有SELinux,如果内核中没有SELinux或者内核参数中 selinux=0 这一项,那么系统就会以一种叫做 non-SE的状态被继续引导启动。如果发现了SELinux,那么/selinux虚拟文件系统将被创建,然后,init通过 /selinux/policyvers来检查内核所支持的SELinux版本。最后,相应的策略数据 /etc/selinux/X/policy/policy.YY就会被装在到内核中去了。

当策略被装载完之后,所有正在运行着的进程(指的就是init和内核的所有线程)都将被指定 system_u:system_r:kernel_t 这样一种上下文(内核线程其实无论在什么时间被创建,其上下文都是system_u:system_r:kernel_t )。当init装载完策略之后,它还要重新执行自己。策略中有一个规则叫domain_auto_trans(kernel_t, init_exec_t, init_t)。他的意思就是当 kernel_t 域执行了一个据有 init_exec_t 类型的可执行文件(如/sbin/init),那么该执行文件对应的进程的域就会自动过渡到 init_t 域(这是/sbin/init正确的所在域)。当这些都完成之后,init就继续完成那些通常的任务来完成机器的启动。内核线程自始至终都以 kernel_t 这个类型运行。

文件和目录的上下文存储于扩展属性当中 (XATTRs)。更多关于XATTRs的信息请参考attr(5), getfattr(1) 和 setfattr(1)的manpage。

简单的说,一个XATTR就是硬盘上某个文件的所有权,它由文件名和其它一些信息组成。对于每个 persistent 文件系统来说,它的每个文件或目录的SELinux上下文就存储在 security.selinux属性当中。虽然/proc文件系统不是persistent 文件系统,但SELinux还是在幕后为其文件和目录做了上下文标记,只是不能用getxattr获得罢了。和它对比,devpts文件系统(应用于 /dev/pts Unix98伪终端)中各个文件(各个伪终端)的上下文是可以通过getxattr来获得的,并可以通过 setxattr 来更改每个设备的上下文(以便sshd等类似程序可以更改tty设备的上下文)。对于那些拥有固定存储的文件系统(ext2, ext3, Reiserfs, XFS, vfat, 等等) 有两种选择用于设定文件上下文:
第一种:文件系统的类型就规定了其内部每一个文件英据有统一的上下文;
第二种:使用 XATTRs 为每个文件标记不同上下文。例如,在iso9660(CD-ROM)文件系统中的每一个文件的上下文都是system_u:object_r:iso9660_t ,这被称做 genfs标记。

Ext2, ext3 和XFS支持 XATTRs 而且 Fedora 系统也支持安全标记名字空间,所以Fedora默认使用 XATTRs 来标记文件的上下文,但这也是可选方法之一。因为 直到 Reiser4发布之前 ,Hans Reiser对支持XATTR没多大兴趣,所以Fedora的 ReiserFS 文件系统不能很好的支持SELinux标记操作。也就是说,使用 ReiserFS 文件系统作为SELinux的根文件系统是不可能的事情。

XFS有一个与XATTRs相关的重要的问题:如果XATTRs不能被装入超级块(inode),那么它们就会被装入数据块,每一个超级块就要使用一个数据块用来装 SELinux XATTR 。建立XFS时,mkfs.xfs在默认情况下创建的数据块大小为4096,超级块大小为256(要是用于安装 SELinux XATTR ,大约缺少30字节)。这就是说,默认的XFS文件系统中,每一个超级块要占用4096字节用来装载 SELinux XATTR ,这对于磁盘空间来说是严重的浪费!当你使用"-i size=512"选项创建一个XFS文件系统时,超级块的大小就变成了512字节,这样就可以将SELinux XATTR 装入超级块,即节省了空间,又提高的性能。512字节的超级块也有可能给其它操作带来好处。所以,如果你使用XFS并且打算将来使用 SELinux 的话,将超级块的大小规定为512字节肯定是个好主意。

如果你使用的是较新的内核(如最新的Fedora内核或标准2.6.8.1内核)并且使用最新的mount工具,那么当你挂载一个文件系统时,有一个选项可以用来为整个文件系统指定上下文标签。比如你要挂载的文件系统是一个邮件池(mail spool),你可以使用"-o context=system_u:object_r:mail_spool_t"选项来挂载他,这样会将其内部的全部文件的上下文标记为 system_u:object_r:mail_spool_t。如果你的这个邮件池很大,而且还是XFS文件系统,这个方法还可以避免上一段所讨论的 inode大小的问题。甚至对于ext3那样的对XATTRs 开销较小的文件系统来说,使用context=选项挂载文件系统也会进一步减少开销,也可以避免为已经建立的文件系统重新设置 SElinux上下文(如果文件系统中文件较多的话,会浪费很长的时间)。