2020-09-02 20:13:35 +08:00
# Android SELinux 详解
## 1.Kernel SELinux 模块
## 2.模式控制
SELinux 有三种工作模式: 强制模式( enforcing) 、宽容模式( permissive) 和关闭模式( disabled)
* enforcing: 代表 SELinux 运作中,且会执行实际的限制;
* permissive: 代表 SELinux 运作中,但只会记录警告讯息并,不执行实际的限制;
* disabled: 代表 SELinux 不会实际运作。
临时设置 SELinux 为 permissive 的方法如下:
```bash
adb root
2021-01-21 20:06:16 +08:00
adb shell setenforce < 0 | 1 >
2020-09-02 20:13:35 +08:00
```
在 Android 系统下,可通过设置 Bootargs 来改变 SELinux 的工作模式,参数、取值范围及说明如下:
```ini
# 设置 SELinux 为强制模式
androidboot.selinux=enforcing
# 设置 SELinux 为宽容模式
androidboot.selinux=permissive
# 设置 SELinux 为关闭模式
androidboot.selinux=disabled
```
2021-01-21 20:04:43 +08:00
可以通过:
```bash
adb shell getenforce
```
获取当前的 SELinux 工作模式。
2020-09-02 21:48:31 +08:00
## 3.SEAndroid
SEAndroid 是在 Android 系统中基于 SELinux 推出的强制访问控制模型,来完善自主访问模型中只要取得 root 权限就可以为所欲为的情况。
2021-01-21 19:06:17 +08:00
SEAndroid 工作大致分为两部分:打标签和根据标签做权限控制。
2020-09-02 21:48:31 +08:00
### 3.1.打标签
2021-03-10 17:04:11 +08:00
SEAndroid 会给所有的文件(包括进程贴上标签),这些标签称为 Security Context。我们可以通过 ls -Z 来查看文件的 Security Context 或者通过 ps -Z 来查看进程的 Security Context。
2020-09-02 21:48:31 +08:00
Security Context 由四部分组成,每一部分用冒号隔开,来看一个例子:
```bash
u:r:init:s0
u:object_r:rootfs:s0
```
2021-03-10 17:04:11 +08:00
* 第一部分 u 代表用户,在 SEAndroid 中只有一个用户,就是 u;
2020-09-02 21:48:31 +08:00
* 第二部分 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
```
2021-03-10 17:04:11 +08:00
attribute_name 表示 type 所属的属性组,一个 type 可以属于多个属性组。这样我们在编译 SELinux 策略的时候通过对属性组编写,就可以应用到该属性组之下的所有 type 了。Android 系统定义的属性组一般都放在 attribute 文件中。
2020-09-02 21:48:31 +08:00
2021-03-10 17:04:11 +08:00
### 3.3.SELinux 中用户和角色的定义
2020-09-02 21:48:31 +08:00
在 roles 文件下定义了角色,每一个角色都有不同的功能,所以每一个角色都和一个域相关联,比如:
```bash
role r types domain
```
就把 r 这个角色和名称为 domain 的这个域关联起来了。一个用户可以拥有多个角色:
```bash
user u roles {r}
```
2021-03-10 17:04:11 +08:00
这样就把用户 u 和角色 r 关联起来了。多个角色之间有层级关系, 比如老板比总经理大, SELinux 用 dominance 来表示,比如:
2020-09-02 21:48:31 +08:00
```bash
dominance{role 老板 {role 总经理;role 总监}}
```
这就表明老板比总经理和总监都大,从 type 来说就是老板会继承总经理和总监所关联的属性组。
### 3.4.基于角色的控制
2021-03-10 17:04:11 +08:00
在 SEAndroid 中定义的 u 和 r 是怎么做到基于角色的控制呢?
2020-09-02 21:48:31 +08:00
使用 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;
```
2021-03-10 17:04:11 +08:00
由于这样使用起来很麻烦,所以 SEAndroid 在 te_macros 中定义了很多宏来帮助我们实现,
2020-09-02 21:48:31 +08:00
比如上面的四句就可以用以下一句宏来实现:
```bash
domain_auto_trans(init_t, apache_exec_t, apache_t)
```
2021-03-10 17:04:11 +08:00
SEAndroid 中还有一个常见的宏就是给一个目录下的新建的文件打标签的宏,比如:
2020-09-02 21:48:31 +08:00
```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 文件都是与预置好的给某些文件或者目录打标签。
2021-03-10 17:04:11 +08:00
### 3.7.apk 以及其使用的 data 目录是如何被 SEAndroid 打标签的
2020-09-02 21:48:31 +08:00
在 PMS 启动的时候会去读取 mac_permissions.xml 文件,该文件中保留了签名和 seinfo 的对应关系,比如 platform 签名对应的 seinfo 是 platform, 这个 seinfo 信息在安装 app 的时候会用到。
2021-03-10 17:04:11 +08:00
然后在安装 app 的时候, PMS 会根据 app 的签名,给该 app 赋予一个 seinfo。这个 seinfo 就是 SELinux 给这个 app 打标签时候的第三个参数: type。
2020-09-02 21:48:31 +08:00
2021-03-10 17:04:11 +08:00
在启动 app 的时候, PMS 会使用到 seapp_contexts 文件,这个文件定义了不同 seinfo 的 app 启动之后的domin, SELinux 就是根据这个文件为 app 进程和其使用的 data 目录打标签。
2020-09-02 21:48:31 +08:00
## 4.TE 文件
2020-09-02 20:13:35 +08:00
在 Android 系统中,可在系统源码中,通过 TE 文件设置程序/文件的 SELinux 属性。
2020-09-02 21:17:09 +08:00
SELinux 分为文件属性和进程属性(运行属性),普通文件属性定义在 file_contexts 中:
2020-09-02 20:13:35 +08:00
```bash
# file_contexts
/(vendor|system/vendor)/bin/demo u:object_r:demo_exec:s0
```
2020-09-02 21:17:09 +08:00
可通过 ls -Z 查看谋文件的 SELinux 文件属性,通过 ps -Z 查看谋运行中程序的进程属性,属性分为 4 组,如:
2020-09-02 20:13:35 +08:00
```bash
u:r:init:s0
```
上述的 u 为 Android 的唯一 user( 有待确认) ; 第二个参数 r 表示进程, object_r 表示文件;第三个参数是这个进程的 type, 在 Android 里面,定义了 100 多个 type; 第四个参数 s0 是一个安全等级。
2020-09-02 21:17:09 +08:00
以下是一个 TE 文件示例:
```bash
type demo, domain;
type demo_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(demo)
allow demo self:capability { sys_admin };
allow demo sysfs:file { create open read write };
allow demo device:dir { create open read write };
```
下面将对该文件的各部分进行讲解。
2020-09-02 21:48:31 +08:00
### 4.1.基本语法
2020-09-02 21:17:09 +08:00
2020-09-02 20:13:35 +08:00
在 TE 文件中,我们一般遇到的语法是这样的:
```bash
# rule_name :规则名称,除了有 allow 还有 dontaudit, auditallow 和 neverallow
# source_type :源类型,主要作用是用来填写一个域(domain)
# target_type : 目标的类型, 即安全上下文, SELinux 一个重要的判断对象
# class :类别,目标(客体)是哪种类别,主要有 File、Dir、Socket、SEAndroid 还有 Binder 等, 在这些基础上又细分出设备字符类型( chr_file) , 链接文件( lnk_file) 等。可以通过 ls -l 查看文件类型
# perm_set :动作集
rule_name source_type target_type:class perm_set
```
解读为:为 source_type 设置一个 rule_name 的规则,规则是对 target_type 的 class 进行 perm_set 的操作,如:
```bash
# 用中文来表述是:允许 factory 域里的进程或服务对类型为 ttyMT_device 的类别为文件( file) 进行 open,read,write,ioctl 操作
allow factory ttyMT_device:chr_file { read write open ioctl};
```
TE 表达式基本上就是这样,下文将按顺序介绍 rule_name、source_type、target_type、class 和 perm_set。
2020-09-02 21:48:31 +08:00
### 4.2.rule_name
2020-09-02 20:13:35 +08:00
allow: 允许某个进程执行某个动作。
2020-09-02 21:17:09 +08:00
auditallow: audit 含义就是记录某项操作。默认 SELinux 只记录那些权限检查失败的操作。 auditallow 则使得权限检查成功的操作也被记录。注意, allowaudit 只是允许记录,它和赋予权限没关系。赋予权限必须且只能使用 allow 语句。
2020-09-02 20:13:35 +08:00
dontaudit: 对那些权限检查失败的操作不做记录。
2020-09-02 21:17:09 +08:00
neverallow: 没有被 allow 到的动作默认就不允许执行的。neverallow 只是显式地写出某个动作不被允许,如果添加了该动作的 allow, 则会编译错误。
2020-09-02 20:13:35 +08:00
2021-01-21 16:12:10 +08:00
### 4.3.source_type
2020-09-02 20:13:35 +08:00
2021-01-21 16:12:10 +08:00
与 source context 对应, 指定一个“域”( domain) , 一般用于描述进程, 该域内的的进程, 受该条 TE 语句的限制。用 type 关键字,把一个自定义的域与原有的域相关联。
2020-09-02 20:13:35 +08:00
最简单地定义一个新域的方式为:
```bash
type shell, domain
```
2020-09-02 21:17:09 +08:00
上面这句话的意思是,将 domain 的全部属性赋予 shell。如果 domain 集合里有一个 allow domain xxxxx, 那么 shell 将会继承它。
2020-09-02 20:13:35 +08:00
2020-09-02 21:48:31 +08:00
### 4.4.target_type
2020-09-02 20:13:35 +08:00
2021-01-21 16:12:10 +08:00
与 target context 对应,指定进程需要操作的客体(文件,文件夹等)类型(安全上下文),同样是用 type 与一些已有的类型,属性相关联
2020-09-02 20:13:35 +08:00
以上面的 ttyMT_device 为例:
```bash
# 定义一个类型,属于 dev_type 属性
type ttyMT_device, dev_type;
2020-09-02 21:17:09 +08:00
# 属性 dev_type 在 external/sepolicyattributes 的定义如下: attribute dev_type;
# 以上 attribute 关键字用于定义一个属性
2020-09-02 20:13:35 +08:00
```
2020-09-02 21:17:09 +08:00
type 可以与一个或多个属性关联,如
2020-09-02 20:13:35 +08:00
```bash
type usb_device, dev_type, mlstrustedobject;
```
2020-09-02 21:17:09 +08:00
另外,还有一个关键字 typeattribute, type 有两个作用,定义(声明)并关联某个属性。可以把这两个作用分开:用 type 进行定义;用 typeattribute 进行关联。示例如下:
2020-09-02 20:13:35 +08:00
```bash
# 定义 httpd_user_content_t, 并关联两个属性
type httpd_user_content_t, file_type, httpdcontent;
# 分成两条语句进行表述:
# 定义 httpd_user_content_t
type httpd_user_content_t;
# 关联属性
typeattribute httpd_user_content_t file_type, httpdcontent;
```
2020-09-02 21:17:09 +08:00
这些类型(安全上下文)会显示地与一个“文件”相关联,如:
2020-09-02 20:13:35 +08:00
file_contexts 里面显式定义了哪些文件属于 ttyMT_device 类型,即用 ls -Z 显示出来文件的安全上下文
```bash
/dev/ttyMT.* u:object_r:ttyMT_device:s0
```
虚拟文件系统的标识方式与普通的文件系统文件标识方式不一样,用 genfscon 来配置。
```bash
# genfscon 的语法是:
genfscon fs_type pathprefix [-file_type] context
```
2020-09-02 21:17:09 +08:00
例如,把 /proc/mtk_demo/demo_file 文件的安全上下文设置成 demo_context:
2020-09-02 20:13:35 +08:00
```bash
genfscon proc /mtk_demo/demo_file u:object_r:demo_context:s0
```
2020-09-02 21:48:31 +08:00
#### 4.4.1.网络对象上下文
2020-09-02 20:13:35 +08:00
```bash
# 例1: 定义端口的上下文
portcon tcp 80 system_u:object_r:http_port_t
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: 定义节点的上下文
2020-09-02 21:48:31 +08:00
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
2020-09-02 20:13:35 +08:00
```
然后你会有一个疑问,这么多属性,这些属性有什么作用,这些属性会有一个地方显式地说明这个属性拥有什么权限,在 external/sepolicy/domain 里就有非常详细的描述。另个在 external/sepolicy/attributes 里定义了很多属性,下面截取了一些常见的定义。
```bash
# All types used for devices.
attribute dev_type;
# All types used for processes.
attribute domain;
# All types used for filesystems.
attribute fs_type;
# All types used for files that can exist on a labeled fs.
# Do not use for pseudo file types.
attribute file_type;
# All types used for domain entry points.
attribute exec_type;
# All types used for property service
attribute property_type;
# All service_manager types created by system_server
attribute system_server_service;
# All domains that can override MLS restrictions.
# i.e. processes that can read up and write down.
attribute mlstrustedsubject;
# All types that can override MLS restrictions.
# i.e. files that can be read by lower and written by higher
attribute mlstrustedobject;
# All domains used for apps.
attribute appdomain;
# All domains used for apps with network access.
attribute netdomain;
# All domains used for binder service domains.
attribute binderservicedomain;
```
2021-01-21 17:57:40 +08:00
### 4.5.Class 和 Permission
2020-09-02 20:13:35 +08:00
2021-01-21 17:57:40 +08:00
Class 指客体的具体类别。用 class 来定义一个客体类别,具体定义方式如下:
2020-09-02 20:13:35 +08:00
```bash
# [external/sepolicy/security_classes示例]
# file-related classes
class filesystem
class file # 代表普通文件
class dir # 代表目录
class fd # 代表文件描述符
class lnk_file # 代表链接文件
class chr_file # 代表字符设备文件
......
# network-related classes
class socket # socket
class tcp_socket
class udp_socket
......
class binder # Android 平台特有的 binder
class zygote # Android 平台特有的 zygote
```
2021-01-21 17:57:40 +08:00
Permission 指具体的操作,系统的定义在 external/sepolicy/access_vectors。有两种定义方法。
2020-09-02 20:13:35 +08:00
用 common 命令定义:
```bash
# 格式为:
common common_name { permission_name ... }
# common 定义的 perm set 能被另外一种 perm set 命令 class 所继承
# 如:
common file {
ioctl read write create getattr setattr lock relabelfrom relabelto
2020-09-02 21:17:09 +08:00
append unlink link rename execute swapon quotaon mounton }
2020-09-02 20:13:35 +08:00
```
用 class 命令定义:
```bash
class class_name [ inherits common_name ] { permission_name ... }
# inherits 表示继承了某个 common 定义的权限
# 注意, class 命令它不能被其他 class 继承
# 继承一个 common, 如继承了 file common
class dir
inherits file
{
2020-09-02 21:17:09 +08:00
add_name
remove_name
reparent
search
rmdir
open
audit_access
execmod
2020-09-02 20:13:35 +08:00
}
# 不继承任何 common, 如
class binder
{
2020-09-02 21:17:09 +08:00
impersonate
call
set_context_mgr
transfer
2020-09-02 20:13:35 +08:00
}
```
然后是一些特殊的配置文件:
```bash
# 所有定义的 attributes 都在这个文件
external/sepolicy/attributes
2020-09-02 21:17:09 +08:00
# 对应了每一个 class 可以被允许执行的命令
2020-09-02 20:13:35 +08:00
external/sepolicy/access_vectors
2020-09-02 21:17:09 +08:00
# Android 中只定义了一个 role, 名字就是 r, 将 r 和 attribute domain 关联起来
2020-09-02 20:13:35 +08:00
external/sepolicy/roles
# 其实是将 user 与 roles 进行了关联,设置了 user 的安全级别, s0 为最低级是默认的级别, mls_systemHigh 是最高的级别
external/sepolicy/users
# 指的是上文命令中的 class, 个人认为这个 class 的内容是指在 android 运行过程中,程序或者系统可能用到的操作的模块
external/sepolicy/security_classes
# 系统定义的宏全在 te_macros 文件
external/sepolicy/te_macros
# 一些配置的文件,包含了各种运行的规则
external/sepolicy/***.te
```
2021-01-21 17:57:40 +08:00
一般常用的 Class 和 Permission 如下表:
| Class | Permission |
|------------|------------|
| file | ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton |
| directory | add_name remove_name reparent search rmdir open audit_access execmod |
| socket | ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind |
| filesystem | mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget |
| process | fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate |
| security | compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy |
| capability | chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap |
| tcp_socket | create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt |
| sock_file | open read write |
| chr_file | create open read write map ioctl |
### 4.6.TE 的正则表达式和集合
2020-09-02 20:13:35 +08:00
TE 文件支持正则表达式,从下面可以看到,通配符是常用的通配符,可以度娘
```bash
/sys/devices/system/cpu(/.*)? u:object_r:sysfs_devices_system_cpu:s0
/sys/power/wake_lock -- u:object_r:sysfs_wake_lock:s0
/sys/power/wake_unlock -- u:object_r:sysfs_wake_lock:s0
/sys/kernel/uevent_helper -- u:object_r:usermodehelper:s0
/sys/module/lowmemorykiller(/.*)? -- u:object_r:sysfs_lowmemorykiller:s0
#############################
# asec containers
/mnt/asec(/.*)? u:object_r:asec_apk_file:s0
/mnt/asec/[^/]+/[^/]+\.zip u:object_r:asec_public_file:s0
```
需要注意的是上面的"--",这里的“--”表示二进制文件,类似的还有
```bash
#‘ -b’ - Block Device ‘ -c’ - Character Device
#‘ -d’ - Directory ‘ -p’ - Named Pipe
#‘ -l’ - Symbolic Link ‘ -s’ - Socket
#‘ --’ - Ordinary file
```
TE 表达式里可以用“{}”来表示一个集合,如:
```bash
# 允许user_t对bin_t类型的文件和文件夹执行read,getattr操作
allow user_t bin_t : { file dir } { read getattr };
# 允许domain对exec_type,sbin_t类型的文件执行execute的动作
allow domain { exec_type sbin_t } : file execute;
```
可以在集合里使用“*”,“-” 和 “~” 三个通配符
```bash
# 允许user_t对bin_t类型的文件和文件夹执行所有操作
allow user_t bin_t : { file dir } *;
# 允许user_t对bin_t类型的文件和文件夹执行除了read,getattr以外的所有操作
allow user_t bin_t : { file dir } ~{ read getattr };
# 允许domain对exec_type类型的文件执行execute的动作, 除了sbin_t以外
allow domain { exec_type -sbin_t } : file execute;
```
2021-01-21 17:57:40 +08:00
### 4.7.TE 的类型转换规则
2020-09-02 20:13:35 +08:00
为什么要转换类型?
init 进程拥有系统的最高权限,如果由 Init 进程 fork, exec 出来的进程默认是与 init 相同的权限,这肯定是不安全的。另一个场景是,由 init 生成的文件,默认也是 init 的读写权限,不方便其他低权限的文件进行访问。
类型转换有两种类型转换:
1. 主体的域的转换
2. 客体的转换
2021-01-21 17:57:40 +08:00
#### 4.7.1.域的转换
2020-09-02 20:13:35 +08:00
type_transition 的完整格式为:
```bash
type_transition source_type target_type : class default_type;
```
举个例子
```bash
type_transition init_t apache_exec_t : process apache_t;
```
init_t 进程执行 type 为 apache_exec_t 的可执行文件时,新的进程转换到 apache_t 域
但是上面只是告诉了转换的过程,却没有说明,有转换的权限,如果要上面的转换成功,还需要下面的语句:
```bash
2020-09-02 21:17:09 +08:00
# 首先,你得让 init_t 域中的进程能够执行 type 为 apache_exec_t 的文件
2020-09-02 20:13:35 +08:00
allow init_t apache_exec_t : file execute;
2020-09-02 21:17:09 +08:00
# 然后,你还得告诉 SELiux, 允许 init_t 做 DT 切换以进入 apache_t 域
2020-09-02 20:13:35 +08:00
allow init_t apache_t : process transition;
2020-09-02 21:17:09 +08:00
# 最后,你还得告诉 SELinux, 切换入口( 对应为 entrypoint 权限)为执行 apache_exec_t 类型的文件
2020-09-02 20:13:35 +08:00
allow apache_t apache_exec_t : file entrypoint;
```
2021-01-21 17:57:40 +08:00
#### 4.7.2.客体的转换
2020-09-02 20:13:35 +08:00
例子:
```bash
type_transition passwd_t tmp_t : file passwd_tmp_t;
```
passwd_t 在 tmp_t 目录下创建文件时,该文件的类型转化为 passwd_tmp_t。这里默认隐含了一个 tmp_t 类型 dir, 因为 file 的容器只能是个 dir。同样的, 如果要上面的语句运行成功, 与需要有相应的权限说明。
对应的必须有两个前提条件:
* The source domain needs permission to add file entries into the directory(这个 process 必须有在这个目录下添加文件的权限).
* The source domain needs permission to create file entries(这个 process 必须有在这个目录下创建以这个 Security Context 为 Label 的文件权限).
如果每个转换之前都需要这样繁锁地权限声音实在很麻烦。TE里允许把这些相同的, 重复使用的语句定义成一个宏, 类似于函数一样。
2021-01-21 17:57:40 +08:00
### 4.8.TE 宏
2020-09-02 20:13:35 +08:00
2020-09-02 21:17:09 +08:00
如果把上面 domain 转换的例子定义成一个宏,应该定义如下:
2020-09-02 20:13:35 +08:00
```bash
2020-09-02 21:17:09 +08:00
# 定义 domain_auto_trans 宏,$1,$2 等等代表宏的第一个,第二个....参数
define('domain_auto_trans', '
# 先 allow 相关权限, domain_trans 宏定义在后面
2020-09-02 20:13:35 +08:00
domain_trans($1,$2,$3)
2020-09-02 21:17:09 +08:00
# 然后设置 type_transition
2020-09-02 20:13:35 +08:00
type_transition $1 $2:process $3;
')
2020-09-02 21:17:09 +08:00
# 定义 domain_trans 宏
define('domain_trans', '
# SEAndroid 在上述三个最小权限上,还添加了自己的一些权限
2020-09-02 20:13:35 +08:00
allow $1 $2:file { getattr open read execute };
allow $1 $3:process transition;
allow $3 $2:file { entrypoint read execute };
allow $3 $1:process sigchld;
dontaudit $1 $3:process noatsecure;
allow $1 $3:process { siginh rlimitinh };
')
```
上面的宏定义在 external/sepolicy/te_macros 里。客体的转换定义如下:
```bash
#####################################
# file_type_auto_trans(domain, dir_type, file_type)
# Automatically label new files with file_type when
# they are created by domain in directories labeled dir_type.
#
2020-09-02 21:17:09 +08:00
define('file_type_auto_trans', '
2020-09-02 20:13:35 +08:00
# Allow the necessary permissions.
file_type_trans($1, $2, $3)
# Make the transition occur by default.
type_transition $1 $2:dir $3;
type_transition $1 $2:notdevfile_class_set $3;
')
2020-09-02 21:17:09 +08:00
define('file_type_trans', '
2020-09-02 20:13:35 +08:00
# Allow the domain to add entries to the directory.
allow $1 $2:dir ra_dir_perms;
# Allow the domain to create the file.
allow $1 $3:notdevfile_class_set create_file_perms;
allow $1 $3:dir create_dir_perms;
')
```
TE 的集合也可以定义成一个宏代替,如读写文件操作集的宏:
```bash
2020-09-02 21:17:09 +08:00
define('x_file_perms', '{ getattr execute execute_no_trans }')
define('r_file_perms', '{ getattr open read ioctl lock }')
define('w_file_perms', '{ open append write }')
define('rx_file_perms', '{ r_file_perms x_file_perms }')
define('ra_file_perms', '{ r_file_perms append }')
define('rw_file_perms', '{ r_file_perms w_file_perms }')
define('rwx_file_perms', '{ rw_file_perms x_file_perms }')
define('create_file_perms', '{ create rename setattr unlink rw_file_perms }')
2020-09-02 20:13:35 +08:00
```
使用方式是:
```bash
allow demo demo_device:chr_file rw_file_perms;
```