访问控制是操作系统信息安全的核心机制,用于限制主体(进程、用户)对客体(文件、设备、端口)的访问权限。Linux 系统默认采用DAC(自主访问控制),而高安全场景(如服务器、车机、安卓设备)会叠加MAC(强制访问控制),其中最主流的实现是SELinux,其在安卓系统的移植版本为SEAndroid。
一、Linux DAC 原理详解
DAC(Discretionary Access Control)是 Linux/Unix 系统的基础访问控制机制,核心是基于用户身份和文件权限位的自主管控,也是用户最常接触的权限模型。
1. 核心要素
(1)主体与客体
- 主体:发起访问请求的实体,包括用户(User)和进程(Process)。进程的权限继承自启动它的用户。
- 客体:被访问的实体,包括文件、目录、设备文件、网络端口等。
(2)用户与组的三类身份
Linux 中每个文件都关联三类身份,权限分别对应用户的访问范围:
- 属主(Owner):文件的创建者或被指定的用户,用
u表示。 - 属组(Group):文件所属的用户组,用
g表示。 - 其他用户(Others):既不是属主也不在属组的用户,用
o表示。
(3)基础权限位(rwx)
每个文件对三类身份分别定义读(r)、写(w)、执行(x)三种权限,权限位共 9 位,对应ls -l输出的权限字段(如rwxr-xr--)。
| 权限字符 | 数值表示 | 文件含义 | 目录含义 |
|---|---|---|---|
| r(读) | 4 | 可读取文件内容 | 可列出目录内文件(ls) |
| w(写) | 2 | 可修改 / 删除文件内容 | 可创建 / 删除目录内文件(mkdir/rm) |
| x(执行) | 1 | 可运行程序 / 脚本 | 可进入目录(cd) |
2. DAC 权限判断流程
Linux 内核判断一个进程能否访问某个文件的优先级顺序如下:
- 检查进程的 有效 UID 是否为文件属主 UID:如果是,应用属主权限(
u段)。 - 若不匹配,检查进程的 有效 GID 是否在文件属组内:如果是,应用属组权限(
g段)。 - 若都不匹配,应用其他用户权限(
o段)。 - 只要任意一段权限满足访问需求(如读操作需要
r位),则允许访问;否则拒绝
核心缺陷:
- 权限自主性过强:文件属主可随意修改权限(如
chmod 777),存在误操作风险。- root 权限无敌:root 用户(UID=0)默认绕过所有 DAC 权限检查,一旦 root 权限泄露,系统完全失控。
- 无细粒度管控:无法基于 “进程用途”“文件类型” 等维度限制访问(如限制某进程只能读特定日志,不能写)。
二、SELinux MAC 原理详解
SELinux(Security-Enhanced Linux)是由 NSA 开发的MAC 实现,核心是通过内核级策略强制限制主体对客体的访问,弥补 DAC 的缺陷。它与 DAC 是叠加关系:只有同时通过 DAC 和 SELinux 检查,访问才会被允许。
1. 核心设计理念
SELinux 抛弃了 DAC “基于用户身份” 的管控逻辑,转而采用TE(Type Enforcement,类型强制)作为核心机制,同时支持 MLS(Multi-Level Security,多级安全)用于高保密场景。日常使用中,TE 是 SELinux 的核心,MLS 极少涉及,本文重点讲解 TE。
2. SELinux 核心要素
(1)安全上下文(Security Context)
SELinux 为所有主体(进程)和客体(文件 / 设备)分配一个标签,称为安全上下文,这是访问控制的核心依据。安全上下文的格式为:user:role:type:level(日常使用中level可忽略,MLS 场景才会用到)。
| 字段 | 含义 | 作用 |
|---|---|---|
| user | SELinux 用户(如unconfined_u) | 关联 Linux 用户,用于权限继承 |
| role | SELinux 角色(如unconfined_r) | 限制用户可执行的进程类型 |
| type | 类型标签(如httpd_t、httpd_sys_content_t) | TE 机制的核心,决定访问权限 |
- 进程的安全上下文:称为domain(域),表示进程的 “身份类型”。
- 文件的安全上下文:称为type(类型),表示文件的 “资源类型”。
(2)策略规则(Policy Rules)
SELinux 策略是一组预定义的规则,描述 “哪个 domain 的进程可以访问哪个 type 的文件,以及允许的操作(读 / 写 / 执行)”。策略规则的核心格式:
allow domain_type file_type : class permission;domain_type:进程的 SELinux 域。file_type:文件的 SELinux 类型。class:访问的客体类别(如file、dir、tcp_socket)。permission:允许的操作(如read、write、execute)。
示例:允许
httpd_t(Apache 进程域)读取httpd_sys_content_t(网页文件类型)的文件allow httpd_t httpd_sys_content_t : file read;
(3)运行模式
SELinux 有 3 种运行模式,决定策略的执行强度:
| 模式 | 命令查看(getenforce) | 核心效果 | 适用场景 |
|---|---|---|---|
| Enforcing(强制模式) | Enforcing | 严格执行策略,拒绝违规访问,并记录日志 | 生产环境 |
| Permissive(宽容模式) | Permissive | 不拒绝违规访问,但记录所有违规行为 | 策略调试、测试环境 |
| Disabled(关闭模式) | Disabled | 完全关闭 SELinux,不进行任何 MAC 检查 | 仅临时排查问题,禁止长期使用 |
(4)AVC 审计日志
当 SELinux 拒绝访问时,会通过AVC(Access Vector Cache)记录详细日志,默认存储在/var/log/audit/audit.log(需安装auditd服务)。日志包含:
- 主体的安全上下文(进程 domain)。
- 客体的安全上下文(文件 type)。
- 被拒绝的操作(如
write)。 - 客体类别(如
file)。
3. SELinux 访问判断流程
当一个进程请求访问文件时,内核的判断顺序是:
- 先执行 DAC 检查:如果 DAC 拒绝(如用户无读权限),直接拒绝访问,不进入 SELinux 检查。
- 再执行 SELinux 检查:
- 提取进程的 domain 和文件的 type。
- 查询策略规则,判断是否存在允许该
domain->type对应操作的规则。 - 若存在规则,允许访问;若不存在,强制拒绝,并记录 AVC 日志。
核心优势:
- 强制管控:策略由管理员定义,进程 / 用户无法绕过(包括 root 用户)。
- 细粒度控制:可基于进程类型、文件类型限制访问(如限制
sshd_t只能访问ssh_key_t类型的文件)。- 最小权限原则:每个进程只拥有完成任务所需的最小权限,降低权限泄露风险。
三、SEAndroid MAC 原理详解
SEAndroid 是SELinux 在安卓系统上的移植版本,由谷歌主导开发,从安卓 4.3 开始成为强制启用的安全机制。其核心原理与 SELinux 一致,但针对安卓的组件化架构做了定制化适配。
1. SEAndroid 与 SELinux 的核心差异
| 特性 | SELinux(Linux) | SEAndroid(安卓) |
|---|---|---|
| 管控对象 | 进程、文件、设备、端口 | 进程、文件、安卓组件(Activity/Service/ContentProvider) |
| 策略架构 | 主要基于 TE 机制 | 1. TE 机制(核心)2. 安卓组件专用规则(如activity类权限) |
| 权限来源 | 系统策略文件(*.pp) | 1. 系统策略(sepolicy)2. 应用签名权限(seapp_contexts) |
| 日志位置 | /var/log/audit/audit.log | logcat(avc:关键字)、dmesg |
| 管理工具 | semanagesetseboolchcon | sepolicy-injectsetenforcels -Z(需 root 权限) |
2. SEAndroid 核心适配点
(1)安卓组件管控
安卓的核心组件(Activity、Service、BroadcastReceiver、ContentProvider)是应用交互的关键,SEAndroid 扩展了 SELinux 的客体类别,新增了activity、service、content_provider等类,并通过策略规则限制组件间的调用。
示例:允许微信的
wechat_app_t域调用系统telephony_service_t类型的 Serviceallow wechat_app_t telephony_service_t : service call;
(2)应用安全上下文分配
安卓通过/seapp_contexts文件定义应用的 SELinux 上下文,分配规则基于:
- 应用的签名(如系统应用、第三方应用)。
- 应用的UID(如
app_1000表示普通应用)。 - 应用的标签(如
privileged表示特权应用)。
普通第三方应用的上下文通常为:u:r:untrusted_app:s0;系统应用为:u:r:system_app:s0。
(3)沙箱隔离
SEAndroid 为每个应用分配独立的 domain,不同应用的进程无法互相访问数据,即使获取 root 权限,也无法绕过 SEAndroid 策略(除非修改策略)。这是安卓 “应用沙箱” 的核心实现。
四、DAC 与 SELinux/SEAndroid MAC 核心对比
| 对比维度 | Linux DAC | SELinux MAC | SEAndroid MAC |
|---|---|---|---|
| 控制类型 | 自主访问控制 | 强制访问控制 | 强制访问控制(安卓定制) |
| 核心依据 | 用户 / 组身份 + 权限位 | 安全上下文(domain/type) + 策略规则 | 安全上下文 + 安卓组件规则 |
| 权限自主性 | 属主可随意修改权限(如chmod 777) | 权限由策略强制定义,用户 / 进程无法修改 | 同 SELinux,应用无法自主修改 |
| root 权限 | root 绕过所有权限检查 | root 受策略限制,无法随意访问 | 同 SELinux,root 需策略授权 |
| 细粒度 | 粗粒度(仅用户 / 组 / 其他三类) | 细粒度(基于进程 / 文件类型) | 极细粒度(支持安卓组件级管控) |
| 默认状态 | Linux 默认启用 | 部分系统默认关闭(如 CentOS 7 需手动开启) | 安卓 4.3+ 默认强制启用 |
| 管理复杂度 | 低(chmodchown即可) | 高(需学习策略语法、上下文管理) | 极高(需适配安卓组件、应用签名) |
| 适用场景 | 普通桌面、非敏感服务器 | 高安全服务器、车机、军工系统 | 安卓设备(手机、平板、车机) |
| 缺陷 | 1. root 权限无敌2. 权限易误配3. 无细粒度隔离 | 1. 策略配置复杂2. 误配会导致系统功能异常 |