• 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);
    }
    

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

  • 相关阅读:
    运营商IMS网间互联互通组网关键技术研究
    所谓0脂低卡的代糖如何影响血糖和胰岛素你真的了解吗?
    stm32无人机-飞行力学原理
    渗透测试信息收集方法和工具分享
    2023福建师范大学计算机考研信息汇总
    BP神经网络
    【计算机网络】传输层(一)—— 传输层概述
    UE4 钥匙开门
    大一Web课程设计:企业网站——HTML+CSS+JavaScript电子购物商城(37页面)
    OAuth2在微服务架构中的典型场景
  • 原文地址:https://www.cnblogs.com/RayWHL/p/16221937.html