SEAndroid kernel 源码解析2--策略执行
来源:互联网 发布:淘宝返利api接口源码 编辑:程序博客网 时间:2024/05/22 13:56
SEAndroid kernel 源码解析1–从hook点到策略点
http://blog.csdn.net/mrhare/article/details/71215391
从hook 点重定向到策略执行函数后,执行avc_has_perm 进行权限检查(还是以socket_create为例)
*/goldfish/security/selinux/avc.c
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested, struct avc_audit_data *auditdata){ struct av_decision avd; int rc; //进行策略检查,检查结果写入到avd中 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); //audit avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); return rc;}
这里先讲一下avc及其相关的结构体
avc_node
avc(Access Vector Cache),用来缓存MAC访问控制策略,在进行策略检查的时候,先到avc中进行检查,如果没有找到,则进行根据安全上下文进行计算,将结果缓存到AVC中,关于安全上下文和策略计算,会在后续下一篇中讲到,这里先主要讲AVC。
/goldfish/security/selinux/avc.c
#define AVC_CACHE_SLOTS 512...struct avc_entry { u32 ssid; u32 tsid; u16 tclass; struct av_decision avd; atomic_t used; /* used recently */};struct avc_node { struct avc_entry ae; struct list_head list; struct rcu_head rhead;};struct avc_cache { struct list_head slots[AVC_CACHE_SLOTS]; spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */ atomic_t lru_hint; /* LRU hint for reclaim scan */ atomic_t active_nodes; u32 latest_notif; /* latest revocation notification */};
/goldfish/security/selinux/include/security.h
struct av_decision{ u32 allowed; u32 decided; u32 auditallowed; u32 auditdeny; u32 seqno;}
avc_cache中有一个长度为512(AVC_CACHE_SLOTS)的指针数组,数组中每一个值对应一个list_head类型的双循环链表,链表用来存储结构体 avc_node 中的类型为list_head 的 list的值,通过链表中的list值可以得到avc_node 的值,每一个avc_node 存储一个策略,这里先介绍一下list_head 然后继续再继续分析。
list_head
这里需要了解list_head的用法,最开始看到这里的时候特别不理解,和平常用的结构体指针用法不一样,通常为:
struct structType{ dataType data; structType *next;};
linux中的普遍用法如下,通过结构体中的指针域来逆向寻找结构体,然后对结构体中的数据域进行操作
struct list_head { struct list_head *next, *prev;};struct structType{ dataType data; struct list_head list;};
关于list_head更详细的介绍:
http://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html
继续上面的分析,真正进行权限检查的是 avc_has_perm_noaudit,将策略检查的结果写到参数av_decision *avd中
/goldfish/security/selinux/avc.c
int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested, unsigned flags, struct av_decision *avd){ struct avc_node *node; struct avc_entry entry, *p_ae; int rc = 0; u32 denied; BUG_ON(!requested); rcu_read_lock(); //查找对应的决策结构体 node = avc_lookup(ssid, tsid, tclass, requested); //未查找到则进行计算 if (!node) { rcu_read_unlock(); //计算策略,并保存到avc_entry.avd中 rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd); if (rc) goto out; rcu_read_lock(); node = avc_insert(ssid, tsid, tclass, &entry); } p_ae = node ? &node->ae : &entry; if (avd) memcpy(avd, &p_ae->avd, sizeof(*avd)); denied = requested & ~(p_ae->avd.allowed); if (denied) { if (flags & AVC_STRICT) rc = -EACCES; else if (!selinux_enforcing || security_permissive_sid(ssid)) avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, tsid, tclass); else rc = -EACCES; } rcu_read_unlock();out: return rc;}
查找策略结构体
/goldfish/security/selinux/avc.c
static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested){ ... node = avc_search_node(ssid, tsid, tclass); ... return node;}
对应的avc_search_node定义如下:
static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass){ struct avc_node *node, *ret = NULL; int hvalue; hvalue = avc_hash(ssid, tsid, tclass); list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list) { if (ssid == node->ae.ssid && tclass == node->ae.tclass && tsid == node->ae.tsid) { ret = node; break; } } if (ret == NULL) { /* cache miss */ goto out; } /* cache hit */ if (atomic_read(&ret->ae.used) != 1) atomic_set(&ret->ae.used, 1);out: return ret;}
avc_cache中定义了一个长度为512的内容为list_head的双链表,利用这个 avc_hash 函数根据ssid, tsid, tclass把avc_node.list散落到对应的一个循环链表中
static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass){ return (ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1);}
比较难理解的是
list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list){ if (ssid == node->ae.ssid && tclass == node->ae.tclass && tsid == node->ae.tsid){ ret = node; break; }}
这是一个宏定义,相当于一个for循环,遍历 slots[havlue] 对应的链表中的list ,并求出该list 对应的avc_node ,把结果赋值给* node*,如果对应的ssid , tsid , tclass 都相等,则找到了缓存的策略点,并将结果返回,如果为找到策略点,则进行计算,这在下一篇中继续分析。
接下来继续分析,找到策略点之后,进行权限的检查操作
- SEAndroid kernel 源码解析2--策略执行
- SEAndroid kernel层源码解析1——从hook点到策略点
- seandroid 策略2
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- SEAndroid策略
- seandroid策略介绍1
- seandroid策略介绍1
- SEAndroid策略分析
- SEAndroid策略分析
- SEAndroid策略介绍1
- java八大基本类型
- JNI高阶知识总结
- oracle--PLSQL
- Muduo之Channel源码解析
- strlen函数的三种写法
- SEAndroid kernel 源码解析2--策略执行
- mina 添加心跳包
- 冒泡排序
- PHP中system()、exec()输出错误信息
- 一般框架min.js 与js 有什么区别,如jquery.min.js与jquery.js有什么区别
- python从oracel中提取ip信息并批量ping后保存
- tcp粘包分析
- HttpClient获取JSON报错406问题解决
- 关于maven一些配置,约定,命令