文章目录1、preface2、selinux架构1LSM架构图2selinux工作模式3selinux决策三要素4Selinux标签机制5策略规则(Policy - Tyle Enforcement)3、源码4、调试通用的selinux排查思路1、preface1、 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 1Android5之后支持selinux如果selinux打开了则需要配置 2新增设备节点(新增驱动)、新增属性、新增rc文件等等均需要在对应的te文件声明 7、selinux与root的关系 1root可以关闭selinux 2但是拥有root不可突破selinux的规则(没有selinuxroot拥有最高权限-增删无阻碍) 3selinux的处理单位是进程te文件描述 进程拥有哪些权限(目录、文件读写权限)2、selinux架构1LSM架构图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来判定是否合规2selinux工作模式模式说明类比Enforcing强制模式违反策略就拒绝并记录日志拦截并记录Permissive宽容模式不阻止只记录日志用于调试打印并记录不但会拦截Disabled完全关闭 SELinux没有保安3selinux决策三要素┌─────────────────────────────────────────┐ │ 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) │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────┘4Selinux标签机制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)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 selinuxgetenforce 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 commBinder:264_2 namewakeup8 devsysfs ino24935 scontextu:r:system_suspend:s0 tcontextu:object_r:sysfs_devices_mstar_ehci:s0 tclassdir permissive1 permissive1 代表不拦截只提示报错和记录日志 报错解析 avc: denied { read }: 表示被拒绝的操作是“读取”。 commBinder:264_2: 表示发起操作的进程名为Binder:264_2。 namewakeup8: 表示操作的对象是名为wakeup8的文件或目录。 devsysfs: 该对象位于sysfs文件系统中。 ino24935: 对象的inode号。 scontextu:r:system_suspend:s0: 发起操作的安全上下文是system_suspend(指的是 system_suspend.te) tcontextu:object_r:sysfs_devices_mstar_ehci:s0: 目标对象的安全上下文是sysfs_devices_mstar_ehci。 tclassdir: 目标对象是一个目录。 permissive1: 当前是在permissive模式下所以只是记录而不真正拒绝。 解决 # 在 system_suspend.te 或相应的 te 文件中添加 allow system_suspend sysfs_devices_mstar_ehci:dir read;