目录
一、SELinux 是什么?
SELinux 全称是 Security-Enhanced Linux,是由美国国家安全局(NSA)和Red Hat开发的一种强制访问控制(MAC)机制,被集成到了Linux内核中。
在Android中,SELinux 从 Android 4.3 开始引入,并从 Android 5.0(Lollipop)起默认启用为强制模式(enforcing),是系统安全的核心。
二、SELinux 的两种模式
SELinux 有两个主要的运行状态:
状态 | 名称 | 说明 |
---|---|---|
Permissive | 宽容模式 | 只记录违规行为,不阻止操作;常用于调试或开发。 |
Enforcing | 强制模式 | 严格执行策略,阻止不合法的行为(如非法访问系统资源)。 |
如何查看当前 SELinux 状态?
在 Android 终端或 ADB shell 中输入:
getenforce
返回
Enforcing
表示SELinux正在强制执行策略。返回
Permissive
表示只是记录日志,不真正限制访问。也可以使用
sestatus
命令(在某些Linux系统上)查看详细信息。
三、SELinux 在 Android 中的作用
限制App权限越界
即使一个应用有root权限,如果违反SELinux策略(比如访问系统核心资源),它的操作依然会被阻止。防止恶意软件提权
限制后台服务或恶意模块在未经授权的情况下获取系统控制权。分区不同安全域(context)
每个进程、文件都有一个安全上下文,像u:object_r:system_file:s0
,用于判断它是否有权执行某操作。
四、为什么Root之后很多设备是 Permissive?
Root工具(如Magisk)经常会将SELinux设置为 Permissive,这样方便修改系统文件或执行本不被允许的操作。
例如,某些模块(如Xposed)需要插桩系统服务,如果SELinux是 Enforcing,这类操作会被阻止。
但 Permissive 模式存在安全风险,因为系统不会阻止任何行为,只记录了日志。
五、开发与调试场景
在开发调试定制ROM、修改系统行为时,为了方便调试,会把SELinux设为Permissive。
发布正式ROM或上架Play商店时,Google强制要求为Enforcing模式。
总结
问题 | 解释 |
---|---|
SELinux能提高安全性吗? | 是的,它为Android添加了一道重要的系统级防线。 |
为什么root后会修改SELinux状态? | 为了获得更高权限访问系统资源,绕开限制。 |
可以手动切换状态吗? | 在root环境下可以通过命令如 setenforce 0/1 进行切换,但需谨慎。 |
🧩 一、什么是 SELinux 策略?
SELinux 策略(policy) 是定义系统中哪些主体(subjects)可以访问哪些客体(objects)以及如何访问的规则集合。
在 Android 或 Linux 中:
主体一般是进程(如
system_server
、vold
)。客体一般是文件、目录、socket、属性等资源。
策略是以 "类型强制访问控制(TE – Type Enforcement)" 的形式存在。
🗂️ 二、SELinux 策略的组成
SELinux策略由多种类型的文件构成:
文件 | 说明 |
---|---|
*.te |
Type Enforcement 文件,定义主体和客体的访问规则(核心策略文件) |
*.fc |
文件上下文文件,定义哪些文件路径属于哪种类型 |
*.if |
接口文件,模块之间共享的抽象接口 |
*.pp |
编译后的策略模块文件(policy package) |
*.cil |
高级策略中使用的中间语言文件 |
📄 三、一个简单的策略例子(.te 文件)
我们看一个简单的策略例子,假设我们创建了一个名为 myapp
的进程:
# myapp.te
# 声明类型
type myapp, domain;
type myapp_exec, exec_type, file_type;
# myapp 允许以 myapp_exec 类型启动
init_daemon_domain(myapp)
# myapp 允许读取 log 文件
allow myapp logd:unix_stream_socket connectto;
# 允许 myapp 读取某个配置文件
allow myapp myconfig_file:file { read open getattr };
解读:
type myapp, domain;
:定义了一个名为myapp
的安全上下文(安全域)。type myapp_exec, exec_type, file_type;
:定义了myapp
的可执行文件类型。init_daemon_domain(myapp)
:允许它作为一个守护进程启动(使用宏简化配置)。allow ...
是核心规则,定义主体如何访问客体。
📁 四、文件上下文(.fc)
这个文件指定哪些路径属于哪种类型(用于挂载策略到文件系统):
# myapp.fc
/system/bin/myapp u:object_r:myapp_exec:s0
/data/myapp/config.xml u:object_r:myconfig_file:s0
🛠️ 五、策略编写流程(开发者视角)
创建类型定义文件(如
myapp.te
)指定文件上下文(
myapp.fc
)构建并安装模块
使用
checkmodule
、semodule_package
工具将.te
文件编译成.pp
模块
加载策略模块
semodule -i myapp.pp
Android使用自己的策略编译系统(Android.bp +
sepolicy
),而不是手动运行这些命令。
🔍 六、常用allow语法
allow <subject> <object>:<class> <permissions>;
示例:
allow myapp sysfs:file { read open };
allow myapp system_file:dir { search };
allow myapp shell_exec:file { execute };
元素 | 含义 |
---|---|
subject |
进程类型(谁在访问) |
object |
被访问的资源类型 |
class |
资源的类别,如 file、dir、socket 等 |
permissions |
允许的操作,如 read 、write 、open 、execute 等 |
🧪 七、开发时如何调试策略?
当 SELinux 阻止某项操作时,它会写入 dmesg
或 /var/log/audit.log
(Android用logcat也能看到)。
日志格式大概如下:
avc: denied { read } for pid=1234 comm="myapp" name="config.xml" dev="sda1" ino=12345 scontext=u:r:myapp:s0 tcontext=u:object_r:myconfig_file:s0 tclass=file
avc: denied { read } for pid=1234 comm="myapp" name="config.xml" dev="sda1" ino=12345 scontext=u:r:myapp:s0 tcontext=u:object_r:myconfig_file:s0 tclass=file
你可以用 audit2allow
工具自动生成建议的策略:
dmesg | audit2allow -m myapp
✅ 总结
内容 | 要点 |
---|---|
策略写在 .te 文件 |
用 allow 声明访问权限 |
每个文件/进程都有 context | type 定义类型,.fc 绑定路径 |
Android 使用宏(如 init_daemon_domain ) |
简化复杂的策略编写 |
日志审计是调试关键 |