SeLinux 基础概念
什么是 SeLinux?
Security-Enhanced Linux (SeLinux) 是由美国国家安全局(NSA)开发的 Linux 内核安全模块,提供强制访问控制(MAC)机制。
核心特性
- 强制访问控制:超越传统 Linux 的自主访问控制
- 基于角色的访问控制:细粒度的权限管理
- 默认拒绝原则:所有未明确允许的操作都被拒绝
- 策略强制执行:系统级的安全策略管理
SeLinux vs 传统 Linux 权限
特性 | 传统 Linux DAC | SeLinux MAC |
---|---|---|
控制基础 | 用户/组权限 | 安全策略规则 |
权限决定者 | 文件所有者 | 系统安全策略 |
灵活性 | 高(用户自主) | 低(强制统一) |
安全性 | 相对较低 | 非常高 |
权限粒度 | 粗粒度(rwx) | 细粒度(100+权限类型) |
默认行为 | 默认允许 | 默认拒绝 |
SeLinux 工作模式
三种运行模式
-
Disabled - 完全禁用
bash# 检查当前模式 getenforce # 输出: Disabled
-
Permissive - 宽容模式
- 记录违规但不阻止操作
- 用于调试和开发阶段
bashsetenforce 0 # 切换到 Permissive 模式
-
Enforcing - 强制执行模式
- 阻止所有违规操作
- 生产环境必须使用此模式
bashsetenforce 1 # 切换到 Enforcing 模式
模式管理命令
bash
# 查看当前模式
getenforce
# 临时切换模式(重启后失效)
setenforce 0 # Permissive
setenforce 1 # Enforcing
# 永久修改(需要修改内核参数)
# 在内核命令行添加:selinux=0 (禁用) 或 enforcing=0 (宽容)
核心架构与组件
安全上下文(Security Context)
SeLinux 使用安全上下文来标识所有系统对象的安全属性。
上下文格式
bash
user:role:type:level
Android 中的简化格式:
bash
u:r:type:s0
组件解析:
- user - 用户标识(Android 中固定为
u
) - role - 角色标识(Android 中固定:主体为
r
,客体为object_r
) - type - 类型标识(最重要的部分)
- level - 安全级别(Android 中固定为
s0
)
实际示例
bash
# 查看文件安全上下文
ls -Z /system/bin/init
# 输出: u:object_r:init_exec:s0
# 查看进程安全上下文
ps -Z | grep system_server
# 输出: u:r:system_server:s0
核心概念
主体(Subject)
- 执行操作的实体
- 通常是进程或线程
- 示例:
system_server
,surfaceflinger
,mediaserver
客体(Object)
- 被访问的资源
- 可以是文件、套接字、设备节点等
- 示例:
/system/bin/init
,/dev/block/mmcblk0
安全类(Security Class)
定义不同类型的资源:
file
- 普通文件dir
- 目录socket
- 套接字process
- 进程property_service
- 属性服务
权限(Permission)
针对每个安全类定义的特定操作:
file
类:read
,write
,create
,unlink
process
类:transition
,signal
,ptrace
socket
类:bind
,connect
,listen
Android SeLinux 实现
策略文件架构
bash
/system/etc/selinux/ # 平台策略 (AOSP)
├── plat_sepolicy.cil
├── plat_file_contexts
├── plat_property_contexts
└── plat_service_contexts
/vendor/etc/selinux/ # 供应商策略
├── vendor_sepolicy.cil
├── vendor_file_contexts
├── vendor_property_contexts
└── vendor_service_contexts
/odm/etc/selinux/ # ODM 策略
/product/etc/selinux/ # 产品策略
关键配置文件
1. 文件上下文(file_contexts)
定义文件系统的安全上下文:
bash
# 格式:路径正则表达式 安全上下文
/system/bin/init u:object_r:init_exec:s0
/data/system/.* u:object_r:system_data_file:s0
/vendor/bin/.* u:object_r:vendor_exec:s0
2. 属性上下文(property_contexts)
定义系统属性的安全上下文:
bash
# 格式:属性前缀 安全上下文
ro.build. u:object_r:build_prop:s0
persist. u:object_r:system_prop:s0
vendor. u:object_r:vendor_prop:s0
3. 服务上下文(service_contexts)
定义 Binder 服务的安全上下文:
bash
# 格式:服务名称 安全上下文
activity u:object_r:activity_service:s0
package u:object_r:package_service:s0
window u:object_r:window_service:s0
4. HWService 上下文(hwservice_contexts)
定义 HIDL 服务的安全上下文:
bash
# 格式:服务名称 安全上下文
android.hardware.light@2.0::ILights u:object_r:hal_light_hwservice:s0
Android 域类型
系统关键域
- system_server - 系统服务进程
- surfaceflinger - 显示合成服务
- mediaserver - 媒体服务
- init - init 进程
- kernel - 内核
应用域
- system_app - 系统预装应用
- platform_app - 平台签名应用
- untrusted_app - 第三方应用
- priv_app - 特权应用
服务域
- netd - 网络守护进程
- vold - 卷管理守护进程
- zygote - 应用孵化器
- audioserver - 音频服务
策略语法详解
基本规则结构
类型定义
sepolicy
# 定义新类型
type system_app, domain;
type system_data_file, file_type;
# 定义属性
attribute coredomain;
attribute appdomain;
# 关联类型到属性
typeattribute system_app coredomain;
访问向量规则(AV Rules)
基本格式:allow source_type(源) target_type(目标):class(类型) permission(权限);
sepolicy
# 基本权限授予
# 允许system_app进程对system/data下的文件进行读写
allow system_app system_data_file:file { read write };
# 常用权限集合
allow system_app system_data_file:file {
create open read write getattr
setattr lock append unlink rename
};
# 进程权限
allow system_app self:process { execmem signal };
高级规则类型
类型转换规则
sepolicy
# 进程域转换
type_transition init shell_exec:process init;
# 文件类型转换
type_transition system_app system_data_file:dir system_app_data_file;
从不允许规则
sepolicy
# 禁止特定操作(覆盖 allow 规则)
neverallow { domain -kernel } self:capability sys_admin;
neverallow appdomain proc:file write;
审核规则
sepolicy
# 记录但不阻止操作
dontaudit system_app unlabeled:dir search;
条件策略
布尔值定义
sepolicy
# 定义布尔值
bool external_storage false;
bool debuggable false;
# 条件规则
allow system_app sdcard_type:dir { read write };
if (external_storage) {
allow system_app removable_device:file { create write };
}
if (debuggable) {
allow system_app debugfs:file { read write };
}
版本条件
sepolicy
# Android 版本特定策略
if (ver >= 10) {
allow system_app new_feature:dir { search };
} else {
# 旧版本兼容性
allow system_app legacy_feature:file { read };
}
实践调试指南
基础调试命令
查看安全上下文
bash
# 查看文件上下文
ls -Z /system/bin/init
ls -Z /data/system/
# 查看进程上下文
ps -Z | grep system_server
ps -Z -A # 查看所有进程
# 查看属性上下文
getprop -Z | head -10
模式管理
bash
# 查看当前模式
getenforce
# 临时切换模式
setenforce 0 # Permissive
setenforce 1 # Enforcing
# 检查 SeLinux 状态
sestatus
SeLinux 拒绝日志分析
日志来源
bash
# 内核日志(dmesg)
dmesg | grep "avc:"
# Android 日志(logcat)
adb logcat | grep "avc:"
# 专门的 SeLinux 日志
adb logcat | grep "selinux"
典型拒绝日志格式
ini
avc: denied { 操作 } for pid=进程ID comm="进程名"
scontext=源上下文 tcontext=目标上下文
tclass=目标类别 permissive=模式
日志解析示例
ini
avc: denied { read } for pid=1234 comm="my_daemon"
name="my_device" dev="tmpfs" ino=1234
scontext=u:r:my_daemon:s0
tcontext=u:object_r:device:s0
tclass=chr_file permissive=0
解析结果:
- 操作 :
read
- 进程 :
my_daemon
(PID: 1234) - 源上下文 :
u:r:my_daemon:s0
- 目标上下文 :
u:object_r:device:s0
- 目标类别 :
chr_file
(字符设备文件)
自动化工具
audit2allow
bash
# 提取拒绝日志并生成策略规则
adb shell dmesg | grep "avc:" | audit2allow
# 输出示例:
# allow my_daemon device:chr_file read;
sepolicy-analyze
bash
# 分析策略文件
sepolicy-analyze /system/etc/selinux/plat_sepolicy.cil
# 检查特定域的权限
sepolicy-analyze /system/etc/selinux/plat_sepolicy.cil -d system_app
策略开发实战
为自定义守护进程添加策略
1. 创建类型定义文件(device/company/sepolicy/my_daemon.te
):
sepolicy
# 定义守护进程类型
type my_daemon, domain;
type my_daemon_exec, exec_type, file_type;
# 标记为守护进程
init_daemon_domain(my_daemon)
# 基本权限
allow my_daemon self:process { execmem fork };
allow my_daemon my_daemon_exec:file { execute read open map };
# 系统资源访问
allow my_daemon system_prop:property_service { set get };
allow my_daemon logd_socket:sock_file write;
allow my_daemon system_data_file:dir search;
allow my_daemon system_data_file:file { read open };
# 设备访问
allow my_daemon device:chr_file { read write open };
# 网络权限
allow my_daemon my_daemon_port:tcp_socket { name_bind };
allow my_daemon port:tcp_socket { name_connect };
2. 文件上下文配置(device/company/sepolicy/file_contexts
):
sepolicy
# 可执行文件上下文
/system/bin/my_daemon u:object_r:my_daemon_exec:s0
# 数据目录上下文
/data/vendor/my_daemon(/.*)? u:object_r:my_daemon_data_file:s0
/vendor/etc/my_daemon/.* u:object_r:my_daemon_config_file:s0
3. 服务上下文配置(device/company/sepolicy/service_contexts
):
sepolicy
vendor.company.my_daemon.IService u:object_r:my_daemon_service:s0
4. 属性上下文配置(device/company/sepolicy/property_contexts
):
sepolicy
persist.vendor.my_daemon. u:object_r:my_daemon_prop:s0
常见问题解决方案
问题 1:文件访问被拒绝
ini
avc: denied { read } for pid=123 comm="my_process"
scontext=u:r:system_app:s0 tcontext=u:object_r:vendor_file:s0
tclass=file
解决方案:
sepolicy
# 在 system_app.te 中添加
allow system_app vendor_file:file read;
问题 2:服务查找被拒绝
ini
avc: denied { find } for pid=456 comm="my_client"
scontext=u:r:platform_app:s0 tcontext=u:object_r:my_service:s0
tclass=service_manager
解决方案:
sepolicy
# 在 platform_app.te 中添加
allow platform_app my_service:service_manager find;
问题 3:属性设置被拒绝
ini
avc: denied { set } for pid=789 comm="my_daemon"
scontext=u:r:my_daemon:s0 tcontext=u:object_r:system_prop:s0
tclass=property_service
解决方案:
sepolicy
# 在 my_daemon.te 中添加
allow my_daemon system_prop:property_service set;
问题 4:套接字连接被拒绝
ini
avc: denied { connectto } for pid=1011 comm="my_app"
scontext=u:r:my_app:s0 tcontext=u:r:my_daemon:s0
tclass=unix_stream_socket
解决方案:
sepolicy
# 在 my_app.te 中添加
allow my_app my_daemon:unix_stream_socket connectto;
策略测试流程
1. 初始测试(Permissive 模式)
bash
# 切换到宽容模式
setenforce 0
# 运行测试用例
./run_tests.sh
# 收集拒绝日志
adb shell dmesg | grep "avc:" > denials.txt
2. 生成策略规则
bash
# 使用 audit2allow 生成规则
cat denials.txt | audit2allow -R
# 手动审查并优化生成的规则
3. 应用和测试策略
bash
# 编译策略文件
mmm /path/to/sepolicy/
# 推送新策略(需要重新打包系统镜像)
adb push sepolicy /vendor/etc/selinux/
# 切换到强制执行模式测试
setenforce 1
./run_tests.sh
高级特性
标签管理
动态重新标记
bash
# 重新标记文件或目录
restorecon -R /data/vendor/my_app/
# 强制重新标记
restorecon -F /system/bin/my_daemon
运行时上下文设置
bash
# 在 init.rc 中设置上下文
service my_daemon /system/bin/my_daemon
class main
user system
group system
seclabel u:r:my_daemon:s0
# 使用 chcon 命令
chcon u:object_r:system_file:s0 /system/bin/my_daemon
条件编译
使用 CIL 条件
sepolicy
; 平台特定条件
(if (call (stringmatch "msm*") (getprop ro.board.platform))
(allow system_app vendor_file:file { read write })
)
; 功能特性条件
(if (call (is_true (getprop ro.feature.my_feature)))
(allow system_app new_device:chr_file { open read })
)
策略模块化
接口定义
sepolicy
# 定义接口供其他模块使用
interface(`my_daemon_domain', `
allow $1 my_daemon:unix_stream_socket connectto;
allow $1 my_daemon_service:service_manager find;
')
模板策略
sepolicy
# 为类似组件创建模板
template(`vendor_daemon_template', `
type $1_daemon, domain;
type $1_daemon_exec, exec_type, file_type;
init_daemon_domain($1_daemon)
allow $1_daemon self:process { execmem };
allow $1_daemon $1_daemon_exec:file { execute };
')
最佳实践
策略编写原则
1. 最小权限原则
sepolicy
# 错误示例:权限过大
allow my_daemon system_data_file:file { read write create delete };
# 正确示例:精确权限
allow my_daemon system_data_file:file { read open };
2. 使用属性组织
sepolicy
# 定义属性
attribute my_component_domain;
# 关联类型
typeattribute my_daemon my_component_domain;
typeattribute my_service my_component_domain;
# 基于属性的规则
allow my_component_domain system_prop:property_service { get set };
3. 避免宽泛规则
sepolicy
# 错误:过于宽泛
allow domain system_file:file read;
# 正确:具体类型
allow system_app system_file:file read;
allow platform_app system_file:file read;
安全审计要点
定期审查
bash
# 检查策略违规
sepolicy-analyze /system/etc/selinux/plat_sepolicy.cil --violations
# 检查域权限
sepolicy-analyze /system/etc/selinux/plat_sepolicy.cil -d untrusted_app
# 生成审计报告
seaudit-report -h
自动化检查
bash
#!/bin/bash
# SeLinux 健康检查脚本
echo "=== SeLinux Status ==="
getenforce
echo "=== Recent Denials ==="
dmesg | grep "avc:" | tail -10
echo "=== Policy Integrity ==="
sepolicy-analyze /system/etc/selinux/plat_sepolicy.cil
echo "=== File Contexts ==="
ls -Z /system/bin/init
ls -Z /system/bin/app_process
性能优化
策略优化技巧
sepolicy
# 使用属性减少规则数量
attribute my_app_domain;
typeattribute system_app my_app_domain;
typeattribute platform_app my_app_domain;
# 基于属性的统一规则
allow my_app_domain system_data_file:dir search;
编译优化
bash
# 使用 CIL 格式提高编译效率
secilc -o /system/etc/selinux/plat_sepolicy.cil plat_sepolicy
# 启用策略缓存
setprop selinux.policy_cache_enabled 1
故障排除清单
常见问题排查
-
权限被拒绝
- 检查当前 SeLinux 模式
- 收集和分析 avc 拒绝日志
- 验证文件/进程安全上下文
-
策略编译失败
- 检查语法错误
- 验证类型和属性定义
- 检查循环依赖
-
启动时策略加载失败
- 验证策略文件完整性
- 检查文件系统权限
- 确认内核 SeLinux 支持
调试命令汇总
bash
# 基础状态检查
getenforce
sestatus
# 上下文查看
ls -Z
ps -Z
# 日志分析
dmesg | grep "avc:"
logcat | grep "selinux"
# 策略工具
audit2allow
sepolicy-analyze
sepolicy-check
通过这份完整的指南,您应该能够深入理解 SeLinux 的工作原理,掌握策略开发和调试技巧,并能够在 Android 系统中有效地管理和维护 SeLinux 安全策略。