|
我们可以看到,代码中使用LIST_FOREACH宏来遍历安全策略链表中的每个策略,然后调用其在mpc_ops中注册的检查函数mpo_##check。mac_policy_ops这个结构中定义了很多事件处理函数,进行细粒度的访问控制,限于篇幅,在此不一一列出。这些函数共分四类:第一类是策略本身的初始化和销毁函数;第二类是对安全标记的操作函数,包括各种内核对象的安全标记的初始化与销毁函数,以及获取与设置安全标记的接口函数;第三类是对文件系统、网络系统及进程对象的标记进行操作的事件处理函数;第四类是检查对各个内核对象的访问是否安全的检查函数。详见mac_policy.h。
2.4 安全策略的注册
分析MLS策略,我们可以发现,安全策略向MAC框架注册是一件很简单的事情。mac_mls.c文件中花了大量篇幅定义了所有的事件处理函数,如前所述,这些函数是安全策略的核心,用于判断访问的安全性等。定义完这些函数后,在源代码的最后,把这些函数的地址填入mac_policy_ops结构中,再用一个MAC_POLICY_SET宏把mac_policy_ops结构挂接到上面提到的mac_policy_list链表中去就可以了,如下:
MAC_POLICY_SET(&mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);
|
其中MPC_LOADTIME_FLAG_NOTLATE标志告诉系统这个KLD模块只能在系统初始化之前加载,这是因为MLS必须在初始化系统内核对象的时候为每个对象附加上自己定义的安全标记。具体地,系统初始化所有的内核对象之前,都会调用mac_policy_ops结构中定义的mpo_init_XXX_label函数,MLS就是在这个函数中在该内核对象的标记里附加上自己的标记的。下面我们分析一下MAC_POLICY_SET宏。
#define MAC_POLICY_SET(mpops, mpname, mpfullname, mpflags, privdata_wanted) \
static struct mac_policy_conf mpname##_mac_policy_conf = { \
#mpname, \
mpfullname, \
mpops, \
mpflags, \
privdata_wanted, \
0, \
}; \
static moduledata_t mpname##_mod = { \
#mpname, \
mac_policy_modevent, \
&mpname##_mac_policy_conf \
}; \
MODULE_DEPEND(mpname, kernel_mac_support, 1, 1, 1); \
DECLARE_MODULE(mpname, mpname##_mod, SI_SUB_MAC_POLICY, \
SI_ORDER_MIDDLE)
|
逻辑也相当简单,我们来走一遍。首先定义一个mac_policy_conf结构,用于描述MLS策略,后续的操作会把这个结构加入到MAC框架所定义的mac_policy_list列表中的。由于MLS策略本身是一个KLD模块,所以必须定义一个moduledata_t结构用于向系统注册模块,在这个结构中指明了由mac_policy_modevent函数处理模块事件,当有模块事件产生的时候将把上面定义的mac_policy_conf结构的地址传给处理函数。
mac_policy_modevent函数的核心代码如下:
case MOD_LOAD:
if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
mac_late) {
printf("mac_policy_modevent: can't load %s policy "
"after booting\n", mpc->mpc_name);
error = EBUSY;
break;
}
error = mac_policy_register(mpc);
break;
case MOD_UNLOAD:
/* Don't unregister the module if it was never registered. */
if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
!= 0)
error = mac_policy_unregister(mpc);
else
error = 0;
break;
|
当模块被LOAD的时候,会调用 mac_policy_register函数,它首先检查该模块是否已注册,如果没有,就会执行下面的代码:
LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
其中mpc为我们上面提到的mac_policy_conf结构的地址,这样到此为止,就把MLS策略添加到MAC框架的策略列表中去了。
2.5 MLS策略源代码分析
根据MLS策略,高安全级别的主体不能写低安全级别的客体,而低安全级别的主体则不能读高安全级别的客体,只有主客体的安全级别相同,才能既读又写。MLS定义了三种标记比较函数:
- mac_mls_dominate_single(a,b):用于检查a的单一标记的安全级是否高于b的单一标记的安全级。这个函数主要用于对内核变量的读、写、查询等事件进行安全性检查。
- mac_mls_single_in_range(a,b):用于检查a的单一标记的安全级是否界于b的标记范围的安全级范围之内。这个函数主要用于对改变内核对象的标记进行安全性检查,当主体改变一个客体的安全标记时,要求新旧标记的安全级别处于主体的安全级别范围之内。
- mac_mls_range_in_range(a,b):用于检查a的安全级范围是否落于b的安全级范围之内。这个函数主要用于改变主体安全级时,要求主体新的安全级必须落于主体当前安全级范围之内。
- mac_mls_equal_single(a,b):用于检查a、b的安全级是否相同。这个函数主要用于网络和设备操作。
以上函数都是调用mac_mls_dominate_element()函数来具体比较的,下面我们就分析一下这个函数,其源代码如下:
static int mac_mls_dominate_element(struct mac_mls_element *a,
struct mac_mls_element *b)
{
int bit;
switch (a->mme_type) {
case MAC_MLS_TYPE_EQUAL:
case MAC_MLS_TYPE_HIGH:
return (1);
case MAC_MLS_TYPE_LOW:
switch (b->mme_type) {
case MAC_MLS_TYPE_LEVEL:
case MAC_MLS_TYPE_HIGH:
return (0);
case MAC_MLS_TYPE_EQUAL:
case MAC_MLS_TYPE_LOW:
return (1);
default:
panic("mac_mls_dominate_element: b->mme_type invalid");
}
case MAC_MLS_TYPE_LEVEL:
switch (b->mme_type) {
case MAC_MLS_TYPE_EQUAL:
case MAC_MLS_TYPE_LOW:
return (1);
case MAC_MLS_TYPE_HIGH:
return (0);
case MAC_MLS_TYPE_LEVEL:
for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
if (!MAC_MLS_BIT_TEST(bit,
a->mme_compartments) &&
MAC_MLS_BIT_TEST(bit, b->mme_compartments))
return (0);
return (a->mme_level >= b->mme_level);
default:
panic("mac_mls_dominate_element: b->mme_type invalid");
}
default:
panic("mac_mls_dominate_element: a->mme_type invalid");
}
return (0);
}
|
上一页 [1] [2] [3] 下一页
|