SeLinux 全面详解

SeLinux 基础概念

什么是 SeLinux?

Security-Enhanced Linux (SeLinux) 是由美国国家安全局(NSA)开发的 Linux 内核安全模块,提供强制访问控制(MAC)机制。

核心特性

  • 强制访问控制:超越传统 Linux 的自主访问控制
  • 基于角色的访问控制:细粒度的权限管理
  • 默认拒绝原则:所有未明确允许的操作都被拒绝
  • 策略强制执行:系统级的安全策略管理

SeLinux vs 传统 Linux 权限

特性 传统 Linux DAC SeLinux MAC
控制基础 用户/组权限 安全策略规则
权限决定者 文件所有者 系统安全策略
灵活性 高(用户自主) 低(强制统一)
安全性 相对较低 非常高
权限粒度 粗粒度(rwx) 细粒度(100+权限类型)
默认行为 默认允许 默认拒绝

SeLinux 工作模式

三种运行模式

  1. Disabled - 完全禁用

    bash 复制代码
    # 检查当前模式
    getenforce
    # 输出: Disabled
  2. Permissive - 宽容模式

    • 记录违规但不阻止操作
    • 用于调试和开发阶段
    bash 复制代码
    setenforce 0  # 切换到 Permissive 模式
  3. Enforcing - 强制执行模式

    • 阻止所有违规操作
    • 生产环境必须使用此模式
    bash 复制代码
    setenforce 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

故障排除清单

常见问题排查

  1. 权限被拒绝

    • 检查当前 SeLinux 模式
    • 收集和分析 avc 拒绝日志
    • 验证文件/进程安全上下文
  2. 策略编译失败

    • 检查语法错误
    • 验证类型和属性定义
    • 检查循环依赖
  3. 启动时策略加载失败

    • 验证策略文件完整性
    • 检查文件系统权限
    • 确认内核 SeLinux 支持

调试命令汇总

bash 复制代码
# 基础状态检查
getenforce
sestatus

# 上下文查看
ls -Z
ps -Z

# 日志分析
dmesg | grep "avc:"
logcat | grep "selinux"

# 策略工具
audit2allow
sepolicy-analyze
sepolicy-check

通过这份完整的指南,您应该能够深入理解 SeLinux 的工作原理,掌握策略开发和调试技巧,并能够在 Android 系统中有效地管理和维护 SeLinux 安全策略。

相关推荐
只想搞钱的肥仔4 小时前
Android thermal (5)_cooling device(下)
android
王廷胡_白嫖帝4 小时前
1. Linux 驱动开发前景
linux·运维·驱动开发
hjlgs4 小时前
Linux中I2C常见问题一
linux
ha20428941944 小时前
Linux操作系统学习之---线程控制
java·linux·学习
某空m4 小时前
【Android】BottomNavigationView实现底部导航栏
android·java
one year.4 小时前
Linux:库制作与原理
linux·运维·服务器
陈苏同学4 小时前
Win11安装 Ubuntu 22.04 子系统 - WSL2 - 安装完迁移到其它盘
linux·运维·ubuntu
蓝色土耳其love5 小时前
centos 7.9 安装单机版k8s
linux·运维·服务器·kubernetes·centos
小贾要学习5 小时前
如何在Linux操作系统环境下使用git命令提交文件到远程仓库
linux·运维·git