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);
}
所以,其就是一个函数指针。这就说得通了。
apparmor 源码分析的更多相关文章
- Docker源码分析(八):Docker Container网络(下)
1.Docker Client配置容器网络模式 Docker目前支持4种网络模式,分别是bridge.host.container.none,Docker开发者可以根据自己的需求来确定最适合自己应用场 ...
- Docker源码分析(四):Docker Daemon之NewDaemon实现
1. 前言 Docker的生态系统日趋完善,开发者群体也在日趋庞大,这让业界对Docker持续抱有极其乐观的态度.如今,对于广大开发者而言,使用Docker这项技术已然不是门槛,享受Docker带来的 ...
- Docker源码分析(一):Docker架构
1 背景 1.1 Docker简介 Docker是Docker公司开源的一个基于轻量级虚拟化技术的容器引擎项目,整个项目基于Go语言开发,并遵从Apache 2.0协议.目前,Docker可以在容器内 ...
- 转载:Docker源码分析(一):Docker架构
原文地址: http://www.infoq.com/cn/articles/docker-source-code-analysis-part1 作者:孙宏亮 1 背景 1.1 Docker简介 D ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
随机推荐
- requests库获取响应流进行转发
遇到了一个问题,使用requests进行转发 requests响应流的时候,出现各种问题,问题的描述没有记录,不过Debug以下终于解决了问题.......下面简单的描述解决方案 response = ...
- A5/web项目连接Oracle 12c数据库报:ORA-01017: 用户名/口令无效
解决办法: 修改Oracle12c用户名密码,再改回来,就ok了,亲测有效.
- Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?
Elasticsearch 提供的首个近似聚合是 cardinality 度量.它提供一个字段的基数, 即该字段的 distinct 或者 unique 值的数目.它是基于 HLL 算法的.HLL 会 ...
- List集合工具类之"将list集合按"指定长度"进行切分Lists.partition和ListUtils.partition"
将list集合按"指定长度"进行切分,返回新的List<List<类型>>集合,如下的: 方法1:List<List<Integer>& ...
- 用JS写一个计算器(兼容手机端)
先看成果:1.PC端2. 首先确立html,有哪些东西我们要知道.布局大概的样子在心里有个数 <!DOCTYPE html> <html> <head> <m ...
- Chrome 已经原生支持截图功能,还可以给节点截图!
昨天 Chrome62 稳定版释出,除了常规修复各种安全问题外,还增加很多功能上的支持,比如说今天要介绍的强大的截图功能. 直接截图 打开开发者工具页面,选择左上角的元素选择按钮(Inspect) W ...
- 前端网络安全——Cookies
一.Cookies特性 1.前端数据存储 2.后端通过http头设置 3.请求时通过http头传给后端 4.前端可读写 5.遵守同源策略 二.Cookies内容 1.域名 2.有效期,删除cookie ...
- Android中的Preference结构的设计与实现
本文主要通过分析源代码来分享Preference的设计和实现方式,让开发者们在今后更加顺手地使用和扩展Preference类,或者在设计其他类似的界面和功能时可以提供参考帮助. Preference概 ...
- Android回到页面并刷新数据
通过对Android Activity的生命周期的了解,需要在后退页面重写onResume()的方法. 建立自己更新数据的函数,并在onCreate()方法中调用. @Override protect ...
- 静态变量和成员变量的区别、final修饰特点、创建对象的内存图、静态内存图
静态变量和成员变量的区别* 静态变量也叫类变量 成员变量也叫对象变量* A:所属不同 * 静态变量属于类,所以也称为为类变量 * 成员变量属于对象,所以也称为实例变量(对象变量)* B:内存中位置不 ...