SEAndroid是在Android系统中基于SELinux推出的强制访问控制模型,来完善自主访问模型中只要取得root权限就可以为所欲为的情况。
SEAndroid工作大致分为两部分:打标签和根据标签做权限控制
打标签
SeAndroid会给所有的文件(包括进程贴上标签),这些标签称为Security Context。我们可以通过ls -Z
来查看文件的Security Context或者通过ps -Z
来查看进程的Security Context.
Security Context由四部分组成,每一部分用冒号隔开,来看一个例子
u:r:init:s0
u:object_r:rootfs:s0
第一部分u
代表用户,在SeAndroid中只有一个用户,就是u
第二部分r
或者object_r
代表用户的角色,如果角色是r
代表的是进程,如果角色是object_r
代表的是文件
第三部分init
或者rootfs
代表类型或者域,一般管文件的这个叫类型,管进程的这个叫域。不同的域拥有不同的权限
第四部分s0
代表安全等级,我们不用关注
根据标签做权限控制
这一部分主要是编写Policy文件了,举个栗子
allow netd proc:file write
简单说一下语法
action domain type:object_class operation
allow
是TE中定义的动作词,表示允许,类似的还有neverallow
表示不允许
netd
表示域,就是进程所属的域,代表某一类进程
proc
表示type,就是file的type,表示一类文件
file
表示object class,是type下的某一个具体类型,是具体给进程操作的东西,这些object class是操作系统预定义好的,在security_class文件中,每一个object class都用class关键字声明
write
表示操作,允许进行的操作也是系统定义好的,在access_vector文件中,每一种object class都对应一组操作,比如common file {write read},或者class bind {read write},其中common和class的区别是common可以被继承,而class定义的操作就是针对于某种object class的,不能被继承
上面的te语句的意思是:允许标签为netd的进程去向标签为proc的file写入数据
接下来看一下如何定义type或者domain,使用type关键字定义
type type_name, attribute_name
,attribute_name表示type所属的属性组,一个type可以属于多个属性组。这样我们在编译SeLinux策略的时候通过对属性组编写,就可以应用到该属性组之下的所有type了
Android系统定义的属性组一般都放在attribute文件中
SeLinux中用户和角色的定义
在roles文件下定义了角色,每一个角色都有不同的功能,所以每一个角色都和一个域相关联,比如
role r types domain
就把r
这个角色和名称为domain的这个域关联起来了
一个用户可以拥有多个角色
user u roles {r}
这样就把用户u
和角色r
关联起来了
多个角色之间有层级关系,比如老板比总经理大,SeLinux用dominance来表示,比如
dominance{role 老板 {role 总经理;role 总监}}
这就表明老板比总经理和总监都大,从type来说就是老板会继承总经理和总监所关联的属性组
基于角色的控制
在SeAndroid中定义的u
和r
是怎么做到基于角色的控制呢?
使用constrain
关键字,形式如下
constrain object_class operation expression
比如constrain file write (u1 == u2 and r1 == r2)
表示只有用户相同并且角色相同的时候,才允许对file这个class执行write操作
其中expression中可以使用的符号有==
,!=
,dom
,domby
(就是前面说的上下级关系)
打标签以及transition
这涉及到两个话题:一个是系统是如何给文件还有进程打标签的。另一个是我们知道进程是一个可执行文件的执行过程,系统可以给某个可执行文件打标签,但是当这个可执行文件运行起来变成进程的时候,这个进程的标签是怎么样的。另外,进程都可以fork,那么一个进程fork出来的进程的标签是怎么样的?这就需要transition了
给进程和文件打标签涉及到两个内核文件:initial_sids和initial_sid_context.
initial_sids算是给我们的标签起别名,因为我们知道一个标签是由四部分组成的字符串,直接使用起来不方便,这个就是给标签起别名,举个栗子
sid security
sid init
然后initial_sid_context是把标签的别名和标签联系起来,举个栗子
sid security u:object_r:kernel:s0
sid init u:object_r:unlabeled:s0
接下来重点看一下transition,使用tryp_transition
关键字
type_transition source_type target_type:object_class result_type
,举个栗子
type_transition init_t apache_exec_t : process apache_t;
这句话是说当一个type为init_t的进程去执行一个type为apache_exec_t的文件时,生成的object_class为process,这个process的类型为apache_t。这样当我们的init进程去执行apache文件的时候,生成的进程type就是apache_t.
理想是美好的,但是要达到上述目的,还需要额外三条语句来配合
allow init_t apache_exec_t : file execute;
允许type为init_t的进程去执行type为apache_exec_t的文件
allow init_t apache_t : process transition;
允许type为init_t的进程切换为type为apache_t的
allow apache_t apache_exec_t : file entrypoint;
允许type为apache_t的进程由type为apache_exec_t的文件生成
由于这样使用起来很麻烦,所以SeAndroid在te_macros中定义了很多宏来帮助我们实现,
比如上面的四句就可以用以下一句宏来实现
domain_auto_trans(init_t, apache_exec_t, apache_t)
SeAndroid中还有一个常见的宏就是给一个目录下的新建的文件打标签的宏,比如
file_type_auto_trans(appdomain, download_file, download_file)
Android系统预先给哪些文件打了标签
Android预先打的标签在XXX_context文件中,比如
/dev/binder u:object_r:binder_device:s0
给/dev/binder文件大的标签是u:object_r:binder_device:s0
一般XXX_context文件都是与预置好的给某些文件或者目录打标签。
apk以及其使用的data目录是如何被SeAndroid打标签的
在PMS启动的时候会去读取mac_permissions.xml文件,该文件中保留了签名和seinfo的对应关系,比如platform签名对应的seinfo是platform,这个seinfo信息在安装app的时候会用到。
然后在安装app的时候,PMS会根据app的签名,给该app赋予一个seinfo.这个seinfo就是Selinux给这个app打标签时候的第三个参数:type
在启动app的时候,PMS会使用到seapp_contexts文件,这个文件定义了不同seinfo的app启动之后的domin, SeLinux就是根据这个文件为app进程和其使用的data目录打标签
在有源码的情况下可以去看一下这两个文件,注释的非常详细
这样就结束了