以下内容节选自本书
Init进程的main()函数有一段代码用来初始化SELinux,如下所示:
int main(......) {
union selinux_callback cb;
cb.func_log = klog_write;
selinux_set_callback(SELINUX_CB_LOG,cb);
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT,cb);
// 初始化SELinux
selinux_initialize();
// 恢复下面目录的安全上下文为系统原始设置
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon_recursive("/sys");
......
}
这里调用的函数selinux_set_callback()的代码位于目录external/libselinux下。我们先看看函数selinux_set_callback()的代码:
voidselinux_set_callback(int type, union selinux_callbackcb)
{
switch(type) {
caseSELINUX_CB_LOG:
caseSELINUX_CB_AUDIT:
caseSELINUX_CB_VALIDATE:
caseSELINUX_CB_SETENFORCE:
caseSELINUX_CB_POLICYLOAD:
}
}
selinux_set_callback()的作用是对一些全局的函数指针赋值,前面Init进程的main()代码中调用函数selinux_set_callback()的结果是将selinux_log的值设置成klog_write,将selinux_audit的值设置成audit_callback,这两个回调函数并没有太多实际的作用。下面再看看selinux_initialize()函数的代码:
staticvoid selinux_initialize(void)
{
if(selinux_android_load_policy() < 0) { //装载并向内核设置Policy
}
selinux_initialize()函数的主要作用是从文件中读取SELinux的配置文件,然后把它设置到内核中,这样SELinux才能开始工作。我们先看看selinux_is_disabled()函数是如何工作的:
staticbool selinux_is_disabled(void)
{
}
}
selinux_is_disabled()函数先判断目录/sys/fs/selinux是否可以访问,因为这个目录是SELinux的虚拟文件系统所在的目录,不能返回说明SELinux被disable了。同时还要判断属性ro.boot.selinux是否等于“disabled”,这个属性值表示SELinux的状态。
selinux_android_load_policy()函数代码如下:
intselinux_android_load_policy(void)
{
// 挂载文件系统selinuxfs到目录/sys/fs/selinux
// 挂载文件系统selinuxfs到目录/selinux
...... // 错误处理
}
selinux_android_load_policy()函数首先把SELinux的虚拟文件系统selinuxfs挂载到目录/sys/fs/selinux,如果不成功,再尝试挂载到目录/selinux。挂载成功后,调用selinux_android_reload_policy()函数来装载策略,函数代码如下:
intselinux_android_reload_policy(void)
{
......
......
}
selinux_android_reload_policy()函数首先打开policy文件,然后把它mmap进内存,最后调用函数security_load_policy()把policy设置到内核中。policy文件的文件名保存在数组constsepolicy_file中,定义如下:
staticconst char *const sepolicy_file[] = {
这两个文件找到一个就可以了,通常是根目录下的sepolicy文件。这个文件就是从源码的external/sepolicy目录下的规则文件编译得到的。
最后我们看看security_load_policy()函数的实现:
intsecurity_load_policy(void *data, size_tlen)
{
...... // 检查参数
}
security_load_policy() 函数很简单,打开 SELinux 虚拟目录(通常是 /sys/fs/selinux )下的“ load ”文件,然后把策略数据写到文件中。