MAC (Mandatory Access Control)
在了解 SEAndroid 之前,有必要先了解两种不同的安全控制策略 DAC (Discretionary Access Control) 和 MAC (Mandatory Access Control)。
DAC (Discretionary Access Control)
Discretionary 中文的意思是: 自主的。所以 DAC 翻译过来就是一种自主的访问权限控制。什么意思呢,就是客体的属主可以自主的决定是否将全部或者部分的访问权限交给其它的主体 。主体 通常指得是进程/线程,客体 则是文件, IO 设备等资源。举个例子,在 Linux 中,A 进程对 B 文件具有全部的权限(可读/可写/可执行),那么这个进程有权限修改这个文件的权限,使得其它进程也能访问这个文件,如通过 chmod 。Linux 的 UGO 权限机制就是 DAC 策略的一种表现形式。DAC 这样的策略,会导致属主的权利太大,如果一旦属于不置信,那么对于客体就是灾难,比如被"不法分子"取得了"超级用户"的权限。
MAC (Mandatory Access Control)
因此,为了解决这个问题,MAC 被提出,Mandatory,强制的,相比于 DAC 策略,在 MAC 中,主体(进程) 访问客体(文件) 的权利取决于操作系统定义的规则,而不是由属主自己决定。所以,即使取得了 root 权限,还是不能"为所欲为"。
前面学习了 Linux 的 UGO 权限模型:

基于 Linux 的 UGO 权限模型,我们再进一步抽象:

其实无论是 DAC 策略还是 MAC 策略,都可以概括为这一安全顶层模型。 这里的主体指的也是进程,而客体通常指的是文件/资源。只不过,相比于 DAC 策略,MAC 策略的 Access Rule 是由操作系统自己定义的一系列针对不同的标签的规则,这样就组成了由系统的强制控制来保证安全性。后面我们需要学习的 SEAndroid 就是属于 MAC 策略的一种实现。
SEAndroid (Security-Enhanced Android)
SEAndroid 是 MAC 的一种实现,所以 SEAndroid 顶层模型也是基于上面说的安全顶层模型的一种实现。
其中标签在 SEAndroid 中称为 security context 也叫做安全上下文(由 user:role:type:security level 组成),主体和客体都有安全上下文; 规则称为 sepolicy。 sepolicy 基于 security context 决定了主体对客体的访问权限。
Security Context (安全上下文)
SEAndroid 的安全上下文,由 user:role:type:security
4个部分组成, 我们分别详细介绍进程的安全上下文和文件的安全上下文
主体(进程)安全上下文
比如我们可以通过 ls-AZ | grep 来查看 init 进程的安全上下文:
shell
ls -AZ | grep init
u:r:init:s0 root 1 0 11041944 12412 ep_poll 0 S init
我们可以看到 init 的安全上下文就是 u:r:init:s0, 虽然有 4 个部分组成,但是主要还是依据 type 来定义安全策略,所有又称为 Type Enforcement, 也是 .te 文件的由来(.te 文件后面我们会学习到)
客体(文件)安全上下文
同样的,我们也可以通过 ls -AZ 来查看某个文件/文件夹的安全上下文,比如,查看手机 /data 目录的安全上下文
shell
ls -AZ | grep data
u:object_r:system_data_root_file:s0 data
可以看到 /data 文件夹的安全上下文是 system_data_root_file
SEPolicy
有了前面描述的安全上下文,那么 SEPolicy 的基本格式是:
shell
allow domian types: classes permissions
上述格式中关键字解释如下:
- domian:用于标识进程或者一系列进程
- types:标识客体
- classes:标识客体的种类
- permissions:可以被允许的操作,如读写
SEPolicy 定义在 .te (Type Enforcement) 文件中,在 Android 系统中通常每个进程都有单独的 .te 文件,举个实际的 adbd.te 文件中例子
shell
// system/sepolicy/private/adbd.te
...
allow adbd system_file:file rx_file_perms
...
根据 SEPolicy 的基本格式,这条规则的意思就是:允许 type 为 adbd 的进程对 type 为 system_file 的文件对象执行获取属性,打开,执行等操作。其中 rx_file_perms 是 read getattr open execute 的一个操作集合。我们再举一个实际的例子结合上面的安全上下文再理解一下:
我们通过 ps -AZ 来查看 adbd 这个进程的安全上下文
shell
ps -AZ | grep adbd
u:r:adbd:s0 shell 2882 1 11095648 7896 ep_poll 0 S adbd
根据安全上下文的格式,可以看到 adbd 进程的 type 为 adbd
接下来通过 ls -AZ 查看 product 这个文件夹的安全上下文
shell
ls -AZ | grep product
u:object_r:system_file:s0 3488 2025-03-07 04:27 product
同样地,根据安全上下文的格式,product 这个文件夹的 type 是 system_file
最后,我们回到 allow adbd system_file:file rx_file_perms 这条 SEPolicy,这条规则就是:允许 adbd 进程对 product 这个分区或其它为 system_file 的文件具有 read getattr open execute 的权限。
后续的学习
基于 SEAndroid 的权限模型,接下来我们要学习的问题就很清楚了,主要是围绕着 subject 的安全上下文 、object 安全上下文 和 sepolicy
- Android 系统是如何确定每一个主体(进程) 的安全上下文?比如说 Init 进程和 Zygote 进程以及其它 App 进程的安装下文是如何确定的
- Android 系统是如何确定客体(文件和 Android 特有的 Property) 的安全上下文?
- 主体访问客体的规则又是如何定义的呢?