增加 SEAndroid 部分内容.
Signed-off-by: rick.chan <chenyang@autoai.com>
This commit is contained in:
parent
061a9ab065
commit
dd3aa88a5f
|
@ -28,7 +28,176 @@ androidboot.selinux=permissive
|
|||
androidboot.selinux=disabled
|
||||
```
|
||||
|
||||
## 3.TE 文件
|
||||
## 3.SEAndroid
|
||||
|
||||
SEAndroid 是在 Android 系统中基于 SELinux 推出的强制访问控制模型,来完善自主访问模型中只要取得 root 权限就可以为所欲为的情况。
|
||||
|
||||
SEAndroid 工作大致分为两部分:打标签和根据标签做权限控制
|
||||
|
||||
### 3.1.打标签
|
||||
|
||||
SeAndroid 会给所有的文件(包括进程贴上标签),这些标签称为 Security Context。我们可以通过 ls -Z 来查看文件的 Security Context 或者通过 ps -Z 来查看进程的 Security Context。
|
||||
|
||||
Security Context 由四部分组成,每一部分用冒号隔开,来看一个例子:
|
||||
|
||||
```bash
|
||||
u:r:init:s0
|
||||
u:object_r:rootfs:s0
|
||||
```
|
||||
|
||||
* 第一部分 u 代表用户,在 SeAndroid 中只有一个用户,就是 u;
|
||||
* 第二部分 r 或者 object_r 代表用户的角色,如果角色是 r 代表的是进程,如果角色是 object_r 代表的是文件;
|
||||
* 第三部分 init 或者 rootfs 等,代表类型或者域,一般管文件的这部分叫类型,管进程的这部分叫域。不同的域拥有不同的权限;
|
||||
* 第四部分 s0 代表安全等级,我们不用关注。
|
||||
|
||||
### 3.2.根据标签做权限控制
|
||||
|
||||
这一部分主要是编写 Policy 文件了,最常见的 Policy 就是 TE 文件,举个栗子:
|
||||
|
||||
```bash
|
||||
allow netd proc:file write
|
||||
```
|
||||
|
||||
简单说一下语法:
|
||||
|
||||
```bash
|
||||
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 关键字定义:
|
||||
|
||||
```bash
|
||||
type type_name, attribute_name
|
||||
```
|
||||
|
||||
attribute_name 表示 type 所属的属性组,一个 type 可以属于多个属性组。这样我们在编译 SeLinux 策略的时候通过对属性组编写,就可以应用到该属性组之下的所有 type 了。Android 系统定义的属性组一般都放在 attribute 文件中。
|
||||
|
||||
### 3.3.SeLinux 中用户和角色的定义
|
||||
|
||||
在 roles 文件下定义了角色,每一个角色都有不同的功能,所以每一个角色都和一个域相关联,比如:
|
||||
|
||||
```bash
|
||||
role r types domain
|
||||
```
|
||||
|
||||
就把 r 这个角色和名称为 domain 的这个域关联起来了。一个用户可以拥有多个角色:
|
||||
|
||||
```bash
|
||||
user u roles {r}
|
||||
```
|
||||
|
||||
这样就把用户 u 和角色 r 关联起来了。多个角色之间有层级关系,比如老板比总经理大,SeLinux 用 dominance 来表示,比如:
|
||||
|
||||
```bash
|
||||
dominance{role 老板 {role 总经理;role 总监}}
|
||||
```
|
||||
|
||||
这就表明老板比总经理和总监都大,从 type 来说就是老板会继承总经理和总监所关联的属性组。
|
||||
|
||||
### 3.4.基于角色的控制
|
||||
|
||||
在 SeAndroid 中定义的 u 和 r 是怎么做到基于角色的控制呢?
|
||||
使用 constrain 关键字,形式如下:
|
||||
|
||||
```bash
|
||||
constrain object_class operation expression
|
||||
```
|
||||
|
||||
比如
|
||||
|
||||
```bash
|
||||
constrain file write (u1 == u2 and r1 == r2)
|
||||
```
|
||||
|
||||
表示只有用户相同并且角色相同的时候,才允许对 file 这个 class 执行 write 操作。其中 expression 中可以使用的符号有 ==,!=,dom,domby(就是前面说的上下级关系)。
|
||||
|
||||
### 3.5.打标签以及 transition
|
||||
|
||||
这涉及到两个话题:一个是系统是如何给文件还有进程打标签的。另一个是我们知道进程是一个可执行文件的执行过程,系统可以给某个可执行文件打标签,但是当这个可执行文件运行起来变成进程的时候,这个进程的标签是怎么样的。另外,进程都可以 fork,那么一个进程 fork 出来的进程的标签是怎么样的?这就需要 transition 了。
|
||||
|
||||
给进程和文件打标签涉及到两个内核文件:initial_sids 和 initial_sid_context.
|
||||
|
||||
initial_sids 算是给我们的标签起别名,因为我们知道一个标签是由四部分组成的字符串,直接使用起来不方便,这个就是给标签起别名,举个例子:
|
||||
|
||||
```bash
|
||||
sid security
|
||||
sid init
|
||||
```
|
||||
|
||||
然后 initial_sid_context 是把标签的别名和标签联系起来,举个例子:
|
||||
|
||||
```bash
|
||||
sid security u:object_r:kernel:s0
|
||||
sid init u:object_r:unlabeled:s0
|
||||
```
|
||||
|
||||
接下来重点看一下 transition,使用 tryp_transition 关键字:
|
||||
|
||||
```bash
|
||||
type_transition source_type target_type:object_class result_type
|
||||
```
|
||||
|
||||
举个例子:
|
||||
|
||||
```bash
|
||||
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。
|
||||
|
||||
理想是美好的,但是要达到上述目的,还需要额外三条语句来配合:
|
||||
|
||||
```bash
|
||||
# 允许 type 为 init_t 的进程去执行 type 为 apache_exec_t 的文件
|
||||
allow init_t apache_exec_t : file execute;
|
||||
# 允许 type 为init_t 的进程切换为 type 为 apache_t 的
|
||||
allow init_t apache_t : process transition;
|
||||
# 允许 type 为 apache_t 的进程由 type 为 apache_exec_t 的文件生成
|
||||
allow apache_t apache_exec_t : file entrypoint;
|
||||
```
|
||||
|
||||
由于这样使用起来很麻烦,所以 SeAndroid 在 te_macros 中定义了很多宏来帮助我们实现,
|
||||
比如上面的四句就可以用以下一句宏来实现:
|
||||
|
||||
```bash
|
||||
domain_auto_trans(init_t, apache_exec_t, apache_t)
|
||||
```
|
||||
|
||||
SeAndroid中还有一个常见的宏就是给一个目录下的新建的文件打标签的宏,比如:
|
||||
|
||||
```bash
|
||||
file_type_auto_trans(appdomain, download_file, download_file)
|
||||
```
|
||||
|
||||
### 3.6.Android 系统预先给哪些文件打了标签
|
||||
|
||||
Android 预先打的标签在 XXX_context 文件中,比如:
|
||||
|
||||
```bash
|
||||
/dev/binder u:object_r:binder_device:s0
|
||||
```
|
||||
|
||||
给 /dev/binder 文件打的标签是 u:object_r:binder_device:s0
|
||||
|
||||
一般 XXX_context 文件都是与预置好的给某些文件或者目录打标签。
|
||||
|
||||
### 3.7.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 目录打标签。
|
||||
|
||||
## 4.TE 文件
|
||||
|
||||
在 Android 系统中,可在系统源码中,通过 TE 文件设置程序/文件的 SELinux 属性。
|
||||
|
||||
|
@ -61,7 +230,7 @@ allow demo device:dir { create open read write };
|
|||
|
||||
下面将对该文件的各部分进行讲解。
|
||||
|
||||
### 3.1.基本语法
|
||||
### 4.1.基本语法
|
||||
|
||||
在 TE 文件中,我们一般遇到的语法是这样的:
|
||||
|
||||
|
@ -83,7 +252,7 @@ allow factory ttyMT_device:chr_file { read write open ioctl};
|
|||
|
||||
TE 表达式基本上就是这样,下文将按顺序介绍 rule_name、source_type、target_type、class 和 perm_set。
|
||||
|
||||
### 3.2.rule_name
|
||||
### 4.2.rule_name
|
||||
|
||||
allow:允许某个进程执行某个动作。
|
||||
|
||||
|
@ -93,7 +262,7 @@ dontaudit:对那些权限检查失败的操作不做记录。
|
|||
|
||||
neverallow:没有被 allow 到的动作默认就不允许执行的。neverallow 只是显式地写出某个动作不被允许,如果添加了该动作的 allow,则会编译错误。
|
||||
|
||||
### 3.3.source_type
|
||||
### 4.4.source_type
|
||||
|
||||
指定一个“域”(domain),一般用于描述进程,该域内的的进程,受该条 TE 语句的限制。用 type 关键字,把一个自定义的域与原有的域相关联。
|
||||
|
||||
|
@ -105,7 +274,7 @@ type shell, domain
|
|||
|
||||
上面这句话的意思是,将 domain 的全部属性赋予 shell。如果 domain 集合里有一个 allow domain xxxxx,那么 shell 将会继承它。
|
||||
|
||||
### 3.4.target_type
|
||||
### 4.4.target_type
|
||||
|
||||
指定进程需要操作的客体(文件,文件夹等)类型(安全上下文),同样是用 type 与一些已有的类型,属性相关联
|
||||
|
||||
|
@ -157,7 +326,7 @@ genfscon fs_type pathprefix [-file_type] context
|
|||
genfscon proc /mtk_demo/demo_file u:object_r:demo_context:s0
|
||||
```
|
||||
|
||||
#### 3.4.1.网络对象上下文
|
||||
#### 4.4.1.网络对象上下文
|
||||
|
||||
```bash
|
||||
# 例1:定义端口的上下文
|
||||
|
@ -166,8 +335,8 @@ portcon tcp 8080 system_u:object_r:http_port_t
|
|||
# 例2:定义网络接口的上下文:
|
||||
netifcon eth0 system_u:object_r:netif_eth0_t system_u:object_r:netmsg_eth0_t
|
||||
# 例3:定义节点的上下文
|
||||
nodecon 10.33.10.66 255.255.255.255 system_u:object_r:node_zeus_t;
|
||||
nodecon 10.33.10.0 255.255.255.0 system_u:object_r:node_any_t
|
||||
nodecon 10.34.10.66 255.255.255.255 system_u:object_r:node_zeus_t;
|
||||
nodecon 10.34.10.0 255.255.255.0 system_u:object_r:node_any_t
|
||||
```
|
||||
|
||||
然后你会有一个疑问,这么多属性,这些属性有什么作用,这些属性会有一个地方显式地说明这个属性拥有什么权限,在 external/sepolicy/domain 里就有非常详细的描述。另个在 external/sepolicy/attributes 里定义了很多属性,下面截取了一些常见的定义。
|
||||
|
@ -202,7 +371,7 @@ attribute netdomain;
|
|||
attribute binderservicedomain;
|
||||
```
|
||||
|
||||
### 3.5.class
|
||||
### 4.5.class
|
||||
|
||||
客体的具体类别。用 class 来定义一个客体类别,具体定义方式如下:
|
||||
|
||||
|
@ -225,7 +394,7 @@ class binder # Android 平台特有的 binder
|
|||
class zygote # Android 平台特有的 zygote
|
||||
```
|
||||
|
||||
### 3.6.perm_set
|
||||
### 4.6.perm_set
|
||||
|
||||
具体的操作,系统的定义在 external/sepolicy/access_vectors。有两种定义方法。
|
||||
|
||||
|
@ -290,7 +459,7 @@ external/sepolicy/te_macros
|
|||
external/sepolicy/***.te
|
||||
```
|
||||
|
||||
### 3.7.TE 的正则表达式和集合
|
||||
### 4.7.TE 的正则表达式和集合
|
||||
|
||||
TE 文件支持正则表达式,从下面可以看到,通配符是常用的通配符,可以度娘
|
||||
|
||||
|
@ -335,7 +504,7 @@ allow user_t bin_t : { file dir } ~{ read getattr };
|
|||
allow domain { exec_type -sbin_t } : file execute;
|
||||
```
|
||||
|
||||
### 3.8.TE 的类型转换规则
|
||||
### 4.8.TE 的类型转换规则
|
||||
|
||||
为什么要转换类型?
|
||||
|
||||
|
@ -346,7 +515,7 @@ init 进程拥有系统的最高权限,如果由 Init 进程 fork,exec 出
|
|||
1. 主体的域的转换
|
||||
2. 客体的转换
|
||||
|
||||
#### 3.8.1.域的转换
|
||||
#### 4.8.1.域的转换
|
||||
|
||||
type_transition 的完整格式为:
|
||||
|
||||
|
@ -373,7 +542,7 @@ allow init_t apache_t : process transition;
|
|||
allow apache_t apache_exec_t : file entrypoint;
|
||||
```
|
||||
|
||||
#### 3.8.2.客体的转换
|
||||
#### 4.8.2.客体的转换
|
||||
|
||||
例子:
|
||||
|
||||
|
@ -390,7 +559,7 @@ passwd_t 在 tmp_t 目录下创建文件时,该文件的类型转化为 passwd
|
|||
|
||||
如果每个转换之前都需要这样繁锁地权限声音实在很麻烦。TE里允许把这些相同的,重复使用的语句定义成一个宏,类似于函数一样。
|
||||
|
||||
### 3.9.TE 宏
|
||||
### 4.9.TE 宏
|
||||
|
||||
如果把上面 domain 转换的例子定义成一个宏,应该定义如下:
|
||||
|
||||
|
|
Loading…
Reference in New Issue