首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

从头开始生成 SELinux(2)

从头开始生成 SELinux(2)

转换成 SELinux要将这个系统转换成支持并启用 SELinux 的系统,我们需要修改开始引导系统的程序 /sbin/init,并添加另外几个软件来构建 SELinux 策略及与 SELinux 进行交互。
SysVinit开始我们可以使用一个干净的 SysVInit 拷贝。从 ftp://ftp.cistron.nl/pub/people/ ... ysvinit-2.86.tar.gz 下载 2.86 版本,或者在 freshmeat 上寻找 SysVinit 页面 上的最新版本。我们可以使用后文中  一节所给出的链接以 zip 文件的形式来下载补丁 (sysvinit-init.c.diff);这个补丁可以使用清单 5 中的过程应用于文件 init.c。这个补丁会在系统引导时加载 SELinux 策略。它引入了一个标志 no_selinux,如果引导命令包括了 -p 选项,这个标志就被设置为 1。如果这个标志被设置了,那么就会给出一条警告消息,然后像正常方式一样引导。否则就调用函数 load_policy(),这个函数是在这个补丁中定义的。
清单 5. 对文件 init.c 应用补丁
1
2
3
4
5
6
7
8
9
10
11
wget ftp://ftp.cistron.nl/pub/people/ ... ysvinit-2.86.tar.gz
cd sysvinit-2.86
cd src
patch -p0 < $ORIG/sysvinit-init.c.diff
make init
(su)
mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
mv /mnt/sbin/init /mnt/sbin/init.good
cp init /mnt/sbin/init
umount /mnt
exit




函数 load_policy() 会将 selinuxfs 文件系统的一个实例加载到 /selinux 目录中,并打开文件 /etc/policy.bin 准备读取内容。注意,/selinux 和 /etc/policy.bin 都是强制使用的名字,这样任何希望使用它的用户空间工具都可以遵守这种命名方式。在编译 SELinux 策略时,我们需要将二进制版本拷贝成 /etc/policy.bin。接下来,load_policy()mmap() 会对文件 /etc/policy.bin 进行映射操作,并调用 security_load_policy,这是在 load_policy 上面定义的。它会依次打开文件 /selinux/load(这是 selinuxfs 文件系统中的一个文件)来写入内容,并将 /etc/policy.bin 的所有内容都写入到 /selinux/load 中。这就是二进制策略在引导时如何加载到内核中的。
创建策略SELinux 是一个灵活的访问控制系统,其访问决策都是由管理员定义的策略来决定的。这些策略依赖于系统中文件的布局和配置。支持 SELinux 的发行版提供了预定义的策略,可以灵活地排除与系统中没有安装的软件有关的策略。然而在本练习中,我们可以定义自己的策略。
由于新对象类和权限不是同时引入的,因此策略最终对内核版本会有一定的依赖。mdp.tar.gz (后面  一节中的 zip 文件)中的程序会根据内核版本号自动构建一个空策略。由于这需要对内核进行分析,因此我们需要向其指出用来为 QEMU 映像编译内核所使用的源代码树。将 mdp.tar.gz 解压到 $ORIG/ 中,并进入结果目录 mdp/。
输入:
./build.sh -k ../linux-2.6.14.
这会编译程序 mdp,并使用内核目录作为一个参数来运行它。mdp 接着会查看内核所了解的对象类和权限,并创建一个包含数据的 SELinux 策略。所生成的策略有一个 SELinux 用户、一个 SELinux 角色以及一个 SELinux 类型。单个类型可以应用于所有的文件、内核对象和进程,它对自己具有完全的访问权限。后面我们会对这个策略进行定制,但是现在它可以用来进行初始化并使用 SELinux。
当 build.sh 运行 mdp 时,它会创建几个文件。我们需要 policy.conf 和 file_contexts。第一个是策略的文本表示,后一个是如何标记文件系统的一些指示。
现在我要将对 policy.conf 的全面学习推迟到后面,因此我们暂时跳过前面 500 到 600 行代码,直接跳到下面这行:
type base_t;
这是该策略中所定义的惟一一个类型。下面这行代码:
role base_r types { base_t };
定义了一个角色 base_r,它与 base_t 类型关联在一起。这意味着角色 code_r 中的一个进程可能会在域 base_t 下面运行。接下来是一些长长的 allow 语句,每个语句指定了一个对象类,这为 domain base_t 下面的进程提供了对为该类定义的所有权限来访问 base_t 类型的对象类的能力。
接下来,策略会定义一个用户 user_u,它与角色 base_r 建立了关联。作为 SELinux 用户 user_u 运行的进程可以在 base_r 角色下面运行。我们早已看到 base_r 是与 base_t 类型关联在一起的,因此这两个语句一起使 user_u:base_r:base_t 成为一个有效的上下文,这意味着允许进程在这个上下文中运行。
下面几行代码也非常有用。首先:
sid kernel user_u:base_r:base_t
将一个有效上下文分配给系统中的第一个进程。两行之后,您可以看到:
sid unlabeled user_u:base_r:base_t
这会将相同的上下文分配给任何没有标记的文件。
现在来看一下文件 file_contexts。其中包括两行内容,格式如下:
<regexp>  <context>
其中 regexp 是一个用来对文件名进行比较的正则表达式,context 是如果这个正则表达式可以匹配就对文件应用的 SELinux 上下文。下面这行代码:
/.* user_u:base_r:base_t
用来将这个上下文分配给系统上的所有文件。
返回列表