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, tclassavc_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 都相等,则找到了缓存的策略点,并将结果返回,如果为找到策略点,则进行计算,这在下一篇中继续分析。


接下来继续分析,找到策略点之后,进行权限的检查操作

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑上ie卸载了怎么办 打开cad浏览器闪退怎么办 dnf进游戏闪退怎么办 苹果8出现闪退怎么办 手机浏览器老是自动打开软件怎么办 打开手机浏览器为什么是英文怎么办 ie浏览器删除掉了怎么办 手机360浏览器卸载不掉怎么办 大学素质拓展学分不够怎么办 专升本学分不够怎么办 电脑连接无线网络网关禁用怎么办 背部毛孔粗大有黑头怎么办 毛孔变粗大长痘怎么办 皮肤粗糙暗黄毛孔大怎么办 毛孔粗大还有痘印怎么办 高一的不爱上数学怎么办 监狱系统需要体测怀孕怎么办 货运从业资格证年审过期了怎么办 科三线路记不住怎么办? 汽车大灯里面起雾水怎么办 二级重伤对方法庭拒绝赔偿怎么办? 在麦当劳工作收到假钞怎么办 东西湖小学分配太远怎么办 农行k令过期了怎么办 穿军训的鞋捂坏了怎么办 联通手机号销户话费怎么办 建行员工所持有的原始股怎么办 孕妇喝了午时茶怎么办 苹果6id被锁了怎么办 苹果手机app密码忘了怎么办 好哥们借钱手上没钱怎么办 武汉ca证书u盾怎么办 判了刑发现还有漏案没判怎么办 高铁旅客漏乘怎么办 水库里面要养殖小龙虾最好怎么办 点读机的笔丢了怎么办 皮肤晒的很黑怎么办 电脑wifi连接受限制怎么办 高中孩子班管理松怎么办 脱式计算有余数怎么办 手机被别人绑定微信怎么办