5

apparmor 源码分析 - RayWHL

 2 years ago
source link: https://www.cnblogs.com/RayWHL/p/16221937.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

apparmor 源码分析

这里不对apparmor做介绍,记录一下源码分析过程。

初始化

static int __init apparmor_init(void)
->  security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), "apparmor");
    ->  该函数主要通过一个结构数组 apparmor_hooks 初始化 HOOK 函数

apparmor_hooks 结构数组分析
具体定义在这

摘取一段分析

static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
    LSM_HOOK_INIT(file_permission, apparmor_file_permission),
}

这里每一个 LSM_HOOK_INIT 都定义了一个 security_hook_list 结构。

security_hook_list 结构定义为:

struct security_hook_list {
        struct hlist_node            list;
        struct hlist_head            *head;
        union security_list_options       hook;
        char                              *lsm;} __randomize_layout;

结合 LSM_HOOK_INIT 宏看:

#define LSM_HOOK_INIT(HEAD, HOOK) \        
    { .head =   &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }

可知,LSM_HOOK_INIT 把一个 security_hook_list 结构体中 head 指针指向 security_hook_heads 的一个成员链表,hook 成员初始化为 HOOK函数。
security_hook_heads 我们后面再看,我们这里推测它是一个全局变量。

security_add_hooks
我们回头继续看 security_add_hooks 函数

void __init security_add_hooks(struct security_hook_list *hooks, int count, char *lsm){
        int i;

        for (i = 0; i < count; i++) {
                hooks[i].lsm = lsm;
                hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
        }
        ...

遍历 apparmor_hooks 结构数组,对每一个数组将该数组添加到 head 指向的列表中。

以上实现即是:将每一个 security_hook_list 挂到全局 security_hook_heads 结构体的某一个成员列表中。而 security_hook_list hook 指向具体函数

security_hook_heads

接下来看看全局 security_hook_heads 是啥

struct security_hook_heads security_hook_heads __lsm_ro_after_init;

定义就一行,是个结构体, __lsm_ro_after_init 是指定的读写权限,这里不管。

security_hook_heads 结构定义为:

struct security_hook_heads {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME;
        #include "lsm_hook_defs.h"
        #undef LSM_HOOK} __randomize_layout;

简短,但令人迷惑。include 会将对应文件内容放到结构体里。
lsm_hook_defs.h 内容片段如下:(剩余内容类似)

LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask)
...
LSM_HOOK(int, 0, file_permission, struct file *file, int mask)

把定义展开,结构体就变成了:

struct security_hook_heads {
    struct hlist_head inode_permission;
    ...
    struct hlist_head file_permission;
    ...
}

展开后,就找到了前面初始化时对应的 file_permission 成员。

调用

apparmor如何调用具体的权限检查函数呢,以 security_file_permission 为例:

int security_file_permission(struct file *file, int mask){
       int ret;
       ret = call_int_hook(file_permission, 0, file, mask);
       ...

call_int_hook 定义在这,不贴出来了,展开后结果:

({
   int RC = 0;
   do {
       struct security_hook_list *P; 
       hlist_for_each_entry(P, &security_hook_heads.file_permission, list) {
           RC = P->hook.file_permission(file, mask);        
           if (RC != 0)
               break;
       }
   } while(0);
})

其会根据全局变量 security_hook_heads 找到 file_permission 成员列表上所有的security_hook_list 结构,并调用 hook 指向的 file_permission 函数。

这个 hook 成员前面略过去了,这里看一下,其定义为 union 类型,具体为:

union security_list_options {
       #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
       #include "lsm_hook_defs.h"
       #undef LSM_HOOK};

定义与 security_hook_heads 有点类似,区别在于 LSM_HOOK 宏展开方式不一样,并且是一个union 类型,对于 file_permission 展开后变成了:

union security_list_options {
   int (*file_permission)( struct file *file, int mask);
}
OBJECTIVEC 复制 全屏

所以,其就是一个函数指针。这就说得通了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK