3 security_compute_sid()
security_compute_sid()函数根据主体的SID、客体的SID及客体类别生成一个安全上下文,并获取该安全上下文对应的SID,函数头下所示:
staticint security_compute_sid(u32 ssid,u32 tsid,u16 orig_tclass,u32 specified,const char *objname,u32 *out_sid,bool kern)
该函数包含7个参数:ssid表示主体的SID;tsid表示客体的SID;orig_class表示客体类别;specified表示访问向量的类型;objname表示客体的名字;out_sid表示生成的SID;kern表示客体类别的类型,即orig_class表示的值是策略中的值还是内核中的值。下面结合源码对该函数的主要执行步骤进行说明:
① 判断安全服务器是否初始化。如果没有,则判断目标客体类别orig_class是否等于SECCLASS_PROCESS,若相等,则生成的SID等于主体的SID,否则等于客体的SID。
② 调用context_init()函数来初始化新建的安全上下文newcontext。
③ 根据参数kern调用相应的函数获取对应的类别值,然后再调用security_is_socket_class()函数判断相应的客体类别是否为套接字类别。
④ 调用sidtab_search()函数获取主体和客体的sid对应的安全上下文。
⑤ 判断客体类别的有效性,如果有效,则获取该类别对应的类别属性。
⑥ 根据类别属性中的默认设置分别设置新生成的安全上下文中的用户标识、角色、类型。
⑦ 以主体的类型,客体的类型和客体类别为键值在策略库的TE规则中查找类型规则,并将结果存放到avdatum中。
⑧ 如果avdatum为空,即不存在固定的规则,则检查使能的条件规则来查找匹配的类型规则。
⑨ 如果存在类型规则,则将新建的安全上下文中的类型设置为指定的类型。
⑩ 根据参数objname调用filename_compute_type()函数来设置新建安全上下文的类型。
11 如果specified中设置了AVTAB_TRANSITION标志,则通过for循环查找策略中的角色转换规则。如果找到指定的转换规则,根根据该规则设置新建的安全上下文中的角色属性。
12 调用mls_compute_sid()函数设置新建的安全上下文中的MLS属性。
13 检查新建的安全上下文的有效性,如果无效,则生成一条审计记录。
14 调用sidtab_context_to_sid()函数获取上下文对应的SID。
15 结束并返回。
4.security_load_policy()
security_load_policy()函数用于加载一套新的安全策略,并使其生效,然后刷新访问向量缓存,并在必要的情况下转换SID表。其函数如下所示:
int security_load_policy(void*data, size_t len)
该函数包含两个参数:data表示二进制形式的策略数据;len表示策略数据的长度。对于该函数,其函数调用流程图如图2-14所示:下面结合源码对该函数的主要执行步骤进行说明:
① 判断ss_initialized变量是否设置,如果没有设置,表示安全服务器还没有进行初始化,此时按如下步骤进行处理:
a. 调用avtab_cache_init()函数对访问向量节点进行初始化。
b.调用policydb_read()函数代表策略库的二进制文件中读取配置数据到策略库结构体中。
c.调用selinux_set_mapping()函数计算seclass_map中客体类别的数量,并将seclass_map中字符形式的类别-权限映射转换为数值形式的类别权限映射。
d.调用policydb_load_isids()函数将策略库中的初始SID加载到SID表中。
e.调用security_load_policycaps()函数对策略所具有的能力进行初始化。
f. 调用selinux_complete_init()函数在策略载入之前对超级块进行设置。
g.调用avc_ss_reset()函数来刷新AVC,并且是相应的权限重新生效。
h.调用selinux_status_update_policyload()函数来修改策略重载的事件。
i. 调用selinux_netlbl_cache_invalidate()函数来使网络标记缓存无效。
j. 结束并返回。
② 调用policydb_read()函数代表策略库的二进制文件中读取配置数据到策略库结构体中。
① 判断原有的策略库和新载入的策略库是否支持MLS。如果两者类型不一样,则记录MLS的状态。
② 调用policydb_load_isids()函数将策略库中的初始SID加载到SID表中,如果函数执行失败,则调用policydb_destroy()函数释放为策略库数据结构申请的内存空间,然后直接返回。
③ 调用selinux_set_mapping()函数计算seclass_map中客体类别的数量,并将seclass_map中字符形式的类别-权限映射转换为数值形式的类别权限映射,如果函数执行失败,则释放相应的存储空间并返回。
④ 调用security_preserve_bools()函数根据策略库中的布尔值对条件策略中的规则进行处理,并将相应的规则放入相应的链表中。
⑤ 调用sidtab_map()函数来将复制旧的sid表到newsidtab中。
⑥ 调用sidtab_map()函数来将newsidtab中其中的相应sid对应的安全上下文的值从旧策略中指定的值转换为新策略指定的值,并在新策略中确定相应的安全上下文的有效性。
⑦ 安装新的策略和SID表。
⑧ 调用policydb_destroy()、sidtab_destroy()和kfree()函数来分别释放旧的策略库、旧的SID表以及旧的映射关系。
⑨ 调用avc_ss_reset()函数来刷新AVC,并且是相应的权限重新生效。
⑩ 调用selinux_status_update_policyload()函数来修改策略重载的事件。
11 调用selinux_netlbl_cache_invalidate()函数来使网络标记缓存无效
12 结束并返回。

图2-14security_load_policy()函数调用流程图返回搜狐,查看更多