以下内容节选自本书
selinux_initialize()函数调用selinux_android_load_policy()函数装载并向内核设置了策略文件后,接着调用了selinux_init_all_handles()函数,这个函数用来装载系统中所有文件和属性的安全上下文,下面我们看看这个函数的代码:
voidselinux_init_all_handles(void)
{
}
selinux_init_all_handles()函数中会初始化sehandle和sehandle_prop两个全局变量,它们将包含所有的安全上下文,下面我们以文件系统为例,看看它是如何实现的,函数selinux_android_file_context_handle()的代码如下:
structselabel_handle*selinux_android_file_context_handle(void)
{
}
这里只是调用了file_context_open()方法,代码如下:
staticstruct selabel_handle*file_context_open(void)
{
}
file_context_open()使用参数seopts调用了get_selabel_handle()函数,seopts是个全局变量,定义如下:
staticconst struct selinux_opt seopts[] = {
{SELABEL_OPT_PATH, "/data/security/current/file_contexts"},
{SELABEL_OPT_PATH, "/file_contexts" },
{ 0, NULL} };
selinux_opt类型的第一项是类型,第二项是根据第一项内容而定,上面数组中保存的是文件file_contexts路径,系统初始化时它在根目录下,以后如果有修改,则会保存在/data/security/current目录中。文件file_contexts中保存的就是系统中所有文件的安全上下文。
下面我们继续分析get_selabel_handle()函数:
staticstruct selabel_handle *get_selabel_handle(const struct selinux_optopts[]) {
}
get_selabel_handle()函数会对数组seopts中的每个文件调用selabel_open()函数,直到返回值不为NULL。实际上就是找到数组中第一个存在的文件并调用selabel_open()函数,注意调用函数时的第一个参数是SELABEL_CTX_FILE,定义为0,第三个参数是1。函数selabel_open()的代码如下:
structselabel_handle *selabel_open(unsigned intbackend,
{
struct selabel_handle *rec =NULL;
...... //参数检查
rec = (struct selabel_handle*)malloc(sizeof(*rec));
......//错误检查
memset(rec, 0,sizeof(*rec));
rec->backend = backend;
rec->validating = selabel_is_validate_set(opts,nopts);
if((*initfuncs[backend])(rec, opts, nopts)) {
}
out:
return rec;
}
selabel_open()函数调用了initfuncs数组中保存的函数指针,数组定义如下
staticselabel_initfunc initfuncs[] = {
};
我们前面强调了参数backend的值为0,所以这里调用的将是函数selabel_file_init()。上面的数组中还有一个函数selabel_property_init(),显然装载属性系统的安全上下文时将调用这个函数。
intselabel_file_init(struct selabel_handle *rec, const structselinux_opt *opts,
{
}
selabel_file_init()中创建了一个saved_data结构,这个结构用来保存所有的安全上下文。对文件的解析是在init()函数中完成了,这个函数有点长,只是在一行行的解析文件,我们就不展开分析了。
得到了文件系统和属性系统的安全上下文后有什么用呢?,我们再看看Init进程中main()函数中调用的restorecon()函数的代码:
intrestorecon(const char *pathname)
{
if(is_selinux_enabled() <= 0 ||!sehandle)
}
restorecon()函数用来设置路径的安全上下文。首先调用selabel_lookup()函数从sehandle中查找文件或目录对应的安全上下文,然后调用lsetfilecon()函数来设置文件或目录的安全上下文。这也就是读取所有文件的安全上下文并保存到sehandle中的用途。下面我们再看看lsetfilecon()函数是如何设置安全上下文的:
intlsetfilecon(const char *path, const security_context_tcontext)
{
}
lsetfilecon()函数实际上是调用系统函数lsetxattr()来设置文件或目录的安全上下文。