文章目录
-
-
- 1、preface
- 2、selinux架构
-
- 1)LSM架构图
- 2)selinux工作模式
- 3)selinux决策三要素
- 4)Selinux标签机制
- [5)策略规则(Policy - Tyle Enforcement)](#5)策略规则(Policy - Tyle Enforcement))
- 3、源码
- 4、调试
-
1、preface
jsx
1、
1)认识selinux(NSA开发)
<https://blog.csdn.net/tkwxty/article/details/104538447>
2)如何处理selinux权限
<https://blog.csdn.net/qq_43804080/article/details/106496536>
2、缩略词
SELinux : Security-Enhanced Linux
LSM : Linux Security Module
MAC : Mandatory Access Control(强制访问控制-SELinux采用的策略)
DAC : Discretionary Access Control(自主访问控制-Linux采用的策略)
AVC : Access Vector Cache(访问向量缓存 - 指的是权限描述表)
TE :typer enforcement
3、SELinux策略
SELinux给每个进程(Subject)和资源(Object,如文件、端口)都打上一个"安全上下文"(Security Context),严格规定谁能访问什么
一句话,te文件 声明 谁(以进程为单位)对谁(资源,以文件、file_context为单位)有权限(write/read)
4、什么情况需要开?
一般不开,过认证会要求开
5、sepolicy影响运行还是编译?
影响运行,运行时校验
6、什么场景下需要使用Selinux
1)Android5之后支持selinux,如果selinux打开了,则需要配置;
2)新增设备节点(新增驱动)、新增属性、新增rc文件等等,均需要在对应的te文件声明;
7、selinux与root的关系
1)root可以关闭selinux
2)但是拥有root不可突破selinux的规则(没有selinux,root拥有最高权限-增删无阻碍)
3)selinux的处理单位是进程,te文件描述 进程拥有哪些权限(目录、文件读写权限);
2、selinux架构
1)LSM架构图
1、LSM架构
┌─────────────────────────────────────────┐
│ Linux Security Module (LSM) │
│ SELinux 挂载点 │
├─────────────────────────────────────────┤
│ │
│ 系统调用入口 │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ │
│ │ open() │───→│ LSM Hook│ │
│ │ read() │ │ 检查点 │ │
│ │ write() │ │ │ │
│ │ exec() │ │ selinux_inode_permission│
│ │ ioctl() │ │ selinux_file_permission │
│ │ mmap() │ │ selinux_bprm_checking │
│ │ bind() │ │ selinux_socket_bind │
│ └─────────┘ └────┬────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ AVC (Access │ │
│ │ Vector Cache)│ │
│ │ │ │
│ │ 缓存决策结果 │ │
│ │ 加速重复检查 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Security Server│ │
│ │ │ │
│ │ 查询 Policy DB │ │
│ │ (sepolicy) │ │
│ │ │ │
│ │ 决定: 允许/拒绝 │ │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 允许: 继续执行 │ │
│ │ 拒绝: -EACCES │ │
│ │ 记录: audit log │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────┘
1、从源码和系统架构的角度来看,SELinux 并不是一个独立运行的软件,而是作为一个 Linux 安全模块(LSM, Linux Security Module) 直接编译进 Linux 内核中的
2、内核级拦截: 当用户空间的程序发起系统调用(如 open, read, execve)时,内核在执行实际操作前,会触发 LSM 框架中的 SELinux 钩子函数(Hooks)。
3、策略语言:SELinux 的策略是用一种专门的声明式语言编写的。这些 .te 文件会被编译成二进制格式(.pp 模块),在系统启动时解析成AVC
4、访问向量缓存(AVC): 为了提高性能,SELinux 不会每次都去遍历庞大的策略规则。它会将已经做出的"允许/拒绝"决策缓存起来,这就是 AVC。只有当缓存未命中时,才会去查询策略数据库。
5、总的来说与ftrace/eBPF(实际也是利用bpf机制)类似,在内核入口处增加钩子,根据AVC来判定是否合规
2)selinux工作模式
| 模式 | 说明 | 类比 |
|---|---|---|
| Enforcing | 强制模式:违反策略就拒绝,并记录日志 | 拦截并记录 |
| Permissive | 宽容模式:不阻止,只记录日志(用于调试) | 打印并记录,不但会拦截 |
| Disabled | 完全关闭 SELinux | 没有保安 |
3)selinux决策三要素
┌─────────────────────────────────────────┐
│ SELinux 决策三要素 │
├─────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌────────┐│
│ │ Subject │ + │ Object │ + │ Action ││
│ │ (主体) │ │ (客体) │ │ (动作) ││
│ │ │ │ │ │ ││
│ │ 进程 │ │ 文件/资源 │ │ 读/写/执行││
│ │ apache │ │ /var/www │ │ read ││
│ │ sshd │ │ /etc/shadow│ │ write ││
│ │ app │ │ /dev/video0│ │ open ││
│ └─────────┘ └─────────┘ └────────┘│
│ │ │ │ │
│ └─────────────┴────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ SELinux Policy│ │
│ │ (安全策略) │ │
│ │ │ │
│ │ allow httpd_t │ │
│ │ var_www_t:file read; ││
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 允许 / 拒绝 │ │
│ │ AVC (Audit) │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────┘
4)Selinux标签机制
1、标签格式user:role:type:level
┌─────────────────────────────────────────┐
│ SELinux 标签系统 │
├─────────────────────────────────────────┤
│ │
│ 用户 (User) u:r:t:s0:s0:c0 │
│ │ │││ │ │ │ │
│ │ │││ │ │ └─ 安全级别 │
│ │ │││ │ └─ 类别 │
│ │ │││ └─ 灵敏度 │
│ │ ││└─ 类型 (最关键!) │
│ │ │└─ 角色 │
│ │ └─ 用户 │
│ │ │
│ │ 示例: u:r:kernel_t:s0 │
│ │ u:r:init_t:s0 │
│ │ u:r:httpd_t:s0 │
│ │ u:r:unconfined_t:s0 │
│ │ │
│ ├─────────────────────────────────────┤
│ │ │
│ │ 文件 (File) │
│ │ system_u:object_r:var_www_t:s0 │
│ │ system_u:object_r:shadow_t:s0 │
│ │ system_u:object_r:device_t:s0 │
│ │ │
│ │ 类型匹配: httpd_t 进程 ←→ var_www_t 文件 │
│ │ 才能访问! │
│ │ │
│ └─────────────────────────────────────┘
│ │
└─────────────────────────────────────────┘
5)策略规则(Policy - Tyle Enforcement)
jsx
1、什么时候用到?-> 新增文件/进程服务
2、有几种te文件,例子
1)设备文件规则te
1、type hello_dev_t, dev_type; //type "", dev_type >> 定义设备类型,一般在device.te中定义
2、/dev/hello u:object_r:hello_dev_t:s0 //定义设备权限,s0 为安全级别,一般在file_contexts.te中定义
2)进程规则te
核心语法:allow 主体 客体:类别 权限
1、allow factory hello_dev_t:chr_file { read write ioctl open }; //授权访问,factory 域中的进程对 hello_dev_t 类型的字符设备文件执行读写操作
3)
1.te文件(静态描述文件) -> 转化为AVC(运行时生成)
3、源码
源码实现
1、/kernel/security/selinux
security/selinux/hooks.c --LSM钩子函数实现
security/selinux/avc.c --AVC缓存
security/selinux/ss/services.c --安全服务器
security/selinux/ss/policydb.c -- 策略数据库
security/selinux/netlabel.c -- 网络标签
2.系统调用open使用的SELinux hooks
/kernel/security/selinux/hooks.c
selinux_inode_permission(struct inode *inode, int mask)
--cred_sid(cred); //获取进程的安全上下文
/kernel/security/selinux/avc.c
--avc_has_perm_noaudit(); //查询安全服务器
--avc_audit_required(); //审计日志处理
--audit_inode_permission(); //返回结果 (允许/拒绝)
3.security_compute_av() - Compute access vector decisions.
/kernel/security/selinux/ss/services.c
security_compute_av(struct selinux_state *state, ssid, tsid, orig_tclass, struct av_decision *avd, struct extended_perms *xperms)
--sidtab_search(sidtab, tsid);
--ebitmap_get_bit();
--context_struct_compute_av()
--map_decision();
4、调试
1、selinux命令
setenforce 0 (临时禁用掉SELinux)
getenforce (得到结果为Permissive)
2、系统上如何打开selinux? - 可以咨询对应方案的PL
/android/device/mediatek/m7332/common/scripts/tvapiservice
function_save_selinux()
{
if [ -f /system/bin/getenforce ] && [ -f /system/bin/setenforce ]; then
selinux=`getenforce`
if [ x${selinux} == xEnforcing ]; then
setenforce 0
fi
fi
}
3、selinux配置文件
1) etc
/system/etc/selinux/*
cat /system/etc/selinux/plat_file_contexts | grep audio
1) 审计日志
/var/log/audit/audit.log
4、查看报错
实时查看:dmesg -w | grep avc
查看dmesg缓存: cat /proc/kmsg | grep avc
通用的selinux排查思路
一、
1. 确认是 SELinux 问题
getenforce → 如果是 Enforcing,可能是 SELinux
setenforce 0 → 临时关闭,如果问题解决,确认是 SELinux
2. 查看拒绝日志
dmesg | grep avc → 找到 avc: denied 行
3. 分析日志
scontext=谁? (进程类型)
tcontext=什么? (目标类型)
{ 操作 } = 被拒绝的动作
4. 判断是否合理
├─ 合理需求 → 修改 .te 策略,添加 allow 规则
├─ 路径错误 → 用 restorecon 恢复正确标签
└─ 恶意访问 → 保持拒绝,修复应用
5. 修改策略
├─ 临时: chcon 修改标签
└─ 永久: 修改 .te 文件,重新编译 sepolicy
二、
1、selinux报错及解决案例 - Permission denied
1)报错日志
avc: denied { read } for comm="Binder:264_2" name="wakeup8" dev="sysfs" ino=24935 scontext=u:r:system_suspend:s0 tcontext=u:object_r:sysfs_devices_mstar_ehci:s0 tclass=dir permissive=1
permissive=1 代表不拦截,只提示报错和记录日志
报错解析:
avc: denied { read }: 表示被拒绝的操作是"读取"。
comm="Binder:264_2": 表示发起操作的进程名为Binder:264_2。
name="wakeup8": 表示操作的对象是名为"wakeup8"的文件或目录。
dev="sysfs": 该对象位于sysfs文件系统中。
ino=24935: 对象的inode号。
scontext=u:r:system_suspend:s0: 发起操作的安全上下文是system_suspend(指的是 system_suspend.te)
tcontext=u:object_r:sysfs_devices_mstar_ehci:s0: 目标对象的安全上下文是sysfs_devices_mstar_ehci。
tclass=dir: 目标对象是一个目录。
permissive=1: 当前是在permissive模式下,所以只是记录而不真正拒绝。
解决:
# 在 system_suspend.te 或相应的 te 文件中添加
allow system_suspend sysfs_devices_mstar_ehci:dir read;