SELinux学习以及问题分析(mtk平台)

理论知识

在学习如何分析问题前,我们首先对其基本概念进行了解以及解析

概念

什么是SELinux,SELinux 即Security-Enhanced Linux,由美国国家安全局(NSA)发起,Secure Computing Corporation (SCC) 和 MITRE 直接参与开发,以及很多研究机构(如犹他大学)一起参与的强制性安全审查机制。该系统最初是作为一款通用访问软件,发布于 2000 年 12 月(代码采用 GPL 许可发布)。在Linux Kernel 2.6 版本后,直接整合进入SELinux,搭建在Linux Security Module(LSM)基础上。目前已经成为最受欢迎、使用最广泛的安全方案。
SELinux 是典型的MAC-Mandatory Access Controls实现,对系统中每个对象都生成一个安全上下文(Security Context),每一个对象访问系统的资源都要进行安全上下文审查。审查的规则包括类型强制检测(type enforcement),多层安全审查(Multi-Level Security),以及基于角色的访问控制(RBAC: Role Based Access Control)。
SELinux 搭建在Linux Security Module(LSM)基础上,关于 LSM 架构的详细描述请参见文章 “Linux Security Modules: General Security Support for the Linux Kernel”,该文章在 2002 年的 USENIX Security 会议上发表。有完整的实现LSM 的所有hook function。

SElinux?SEAndroid?

Android 是建立在标准的Linux Kernel 基础上的,自然也可以开启SELinux。在通用移动平台上,通常很少开启这样的安全服务,Google 为了进一步增强Android 的安全性,经过长期的准备,目前已经在Android 5.0(L) 上有完整地开启SELinux,并对SELinux 进行深入整合形成了SEAndroid。

SELinux在Android的更新过程

K 4.4 针对netd, installd, zygote, vold 四个原本具有root 权限的process,以及它们fork 出的子进程启用Enforce 模式。

  • L 版本普遍性开启SELinux Enforce mode。
  • Permissive 模式,只打印audit 异常LOG,不拒绝请求;Enforce 模式,既打印audit 异常LOG,也拒绝请求。

从Android N 版本开始的后续版本,Google都会要求强制性开启SELinux,以保证手机安全。
从Android O 版本后,Google大幅度地增强了SELinux的限制,特别是限制System/Vendor之间的交叉使用,如VNDK的权限控制就主要由selinux来控制。
总体来说,Selinux 在android上的使用过程是一个从具体启用到整体启用、从粗粒度限制到精细控制的过程。

SELinux 给Android 带来的影响

  1. 严格限制了ROOT 权限,以往ROOT “无法无天” 的情况将得到极大的改善。
  2. 通过SELinux保护,降低系统关键进程受攻击的风险,普通进程将没有权限直接连接到系统关键进程。
  3. 进一步强化APP的沙箱机制,确保APP难以做出异常行为或者攻击行为。
  4. 将改变APP一旦安装权限就已经定死的历史,APP权限动态调整将成为可能。

SELinux mode

SELinux分为两种模式,即分别为Permissve Mode(宽容模式)和Enfocing Mode(强制模式)

  1. Permissive Mode:只通过Kernel Audit System 记录LOG,但不真正拦截访问。
  2. Enfocing Mode:不止会记录日志,也会真正进行拦截访问

一般在调试时候使用Permissive Mode,然后在最后修正时使用Enfocing Mode一次修正,在量产阶段保护系统。

如何在boot阶段改变SELinux模式

步骤1:


(使用lk的平台:) /vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mtxxxx/rules.mk

(使用lk2的平台:)/vendor/mediatek/proprietary/bootable/bootloader/lk2/platform/mediatek/mtxxxx/rules.mk
中,将:

choose one of following value -> 1: disabled/ 2: permissive /3: enforcing
SELINUX_STATUS := 3

修改为:

choose one of following value -> 1: disabled/ 2: permissive /3: enforcing
SELINUX_STATUS := 2
步骤2(只在 user load 中需要这一步操作):

/system/core/init/selinux.cpp

bool IsEnforcing() {
return false; //强制将 SELinux 切到 permissive 模式。
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
步骤3(只在 Android R 及后续版本的 user load 中需要这一步操作) :

对于kernel-4.1x版本:
在alps/kernel-x.xx/arch/armxx/configs/xxxx_defconfig (注意不是 xxxx_debug_defconfig,debug_defconfig 是eng load 的)中,设置:
CONFIG_SECURITY_SELINUX_DEVELOP=y
例如:
alps/kernel-4.14/arch/arm64/configs/k69v1_64_tee_cts_defconfig

对于Android S及后续版本中的kernel-5.10及后续版本的GKI2.0平台(如:MT6983/MT6895/MT6879)的mgk defconfig中,设置:
CONFIG_SECURITY_SELINUX_DEVELOP=y
例如:
alps/kernel-5.10/arch/arm64/configs/mgk_64_k510_defconfig

步骤4(只在 Android S及后续版本中的kernel-5.10及后续版本的GKI2.0平台(如:MT6983/MT6895/MT6879)中需要这一步操作):

禁用prebuilt boot.img替换:
在device/mediatek/vendor/common/BoardConfig-vext.mk中,将
MTK_USE_PREBUILT_BOOTIMAGE := yes
修改为:
MTK_USE_PREBUILT_BOOTIMAGE := no

DAC and MAC

DAC 即 Discretionary Access control,自主访问控制,即系统只提供基本的验证,完整的访问控制由开发者自己控制。
MAC 即 Mandatory Access control,强制性访问控制,即系统针对每一项访问都进行严格限制,具体的限制策略由开发者给出。

Linux DAC

Linux DAC 采用了一种非常简单的策略,将资源访问者分成三类,分别是Owner, Group, Other; 资源针对这三类访问者设置不同的访问权限。而访问权限又分成 read, write, execute。
访问者通常是进程,有自己的uid/gid,通过uid/gid 和 文件权限匹配,来确定是否可以访问。
将Root权限根据不同的应用场景划分成许多的Root Capabilities,其中如果有CAP_DAC_OVERRIDE 这项的话,可以直接绕过Linux DAC 限制。

Linux DAC 有明显的不足,其中一个重要点就是Root 权限 “无法无天”,几乎可以做任意事情,一旦入侵者拿到root 权限,就已经完全掌控了系统。另外,每一个进程默认都拿到对应这个用户的所有权限,可以改动/删除这个用户的所有文件资源。很明显,这个难以防止恶意软件。

Linux MAC

Linux MAC 针对DAC 的不足,要求系统对每一项访问进行检查,每访问一个文件资源都需要进行针对性的验证。而这个针对性的验证,是根据已经定义好了的策略进行的。在Linux Kernel中,所有的MAC机制都搭建在Linux Security Modules (LSM) 基础上,包括:SELinux、Apparmor、Smack 和 TOMOYO Linux等。目前SELinux已经成了事实上的行业标准。

相对于Linux DAC,MAC 可以明显弥补DAC 的缺陷。一方面,限制了Root 权限,即使你有root 权限,如果无法通过MAC 验证,那么一样地无法真正执行相关的操作。另外,对每一项权限进行了更加完整的细化,可限制用户对资源的访问行为。

.查看Security Context

使用ps -A -Z 或者cat proc/PID/attr/current,查看当前进程可用ID
在这里插入图片描述
查看文件的Security Context 用:ls -Z
在这里插入图片描述

SELinux Policy limited by Google

从一开始,Google 就已经通过neverallow 语法以及 CTS 测试对selinux policy 进行了初步限制。

  1. 维持system/sepolicy 与Google AOSP一致,尽量不要修改。特别是不要去除任何的neverallow 语句。

  2. 严禁修改untrusted_app.te,放开untrusted_app 的权限。

  3. 系统关键进程启动长时间运行的process,必须进行domain 切换。比如netd, installd, vold, zygote 等。

  4. Native thread 严禁使用kernel 标签,而kernel thread 除init 外,都应当是kernel 标签。

  5. 在user build 中不能存在如su, recovery, init_shell 标签的进程。

  6. 在user build 中所有的process 都必须是Enforce Mode。

在后续的版本更新中,Google 导入了大批量的限制性 neverallow 语法,特别是从O 版本开始针对System/Vendor 的分离,进行了大量针对性的限制,具体可以参考Google 在/system/sepolicy 中所设定的neverallow 语句。

问题的发现以及快速分析

确认与SELinux相关

要分析问题,我们首先需要找到一个方向。那么我们如何快速找到问题的发生点确认问题是否与SELInux相关呢?主要是两个方法

  1. 将SELinux 调整到Permissive 模式测试
    将SELinux 模式调整到Permissive 模式,然后再测试确认是否与SELinux 约束相关。
    ENG 版本:
    adb shell setenforce 0
    如果还能复现问题,则基本可以确定当前root cause与SELinux 无关。如果原本很容易复现,而Permissive mode 不能再复现,那么就可能关系比较大。

  2. 查看LOG 中是否有标准的SELinux Policy Exception
    在Kernel LOG / Main Log 中查询关键字 “avc:” 看看是否有SELinux Policy Exception,并进一步确认这个异常是否与当时的逻辑相关。

如何设置与确认SELinux 模式?

如何确认SELinux 模式

在ENG/USER 版本中,都可以使用getenforce 命令进行查询,如:
root@mt6589_phone_720pv2:/ # getenforce
getenforce
Enforcing

如何设置SELinux 模式

在ENG/USERDEBUG 版本中,可以使用setenforce 命令进行设置:
adb shell setenforce 0 //设置成permissive 模式
adb shell setenforce 1 //设置成enforce 模式
在USER 版本中无法使用setenforce 命令进行设置。

如何分析SELinux Policy Exception

我们来看一下,一份非常典型的SELinux问题报错。

<5>[ 27.706805] (3)[304:logd.auditd]type=1400 audit(1420041991.220:17): avc: denied { execute } for pid=2182 comm=“app_process” path=“/data/dalvik-cache/arm64/system@framework@boot.oat” dev=“mmcblk0p18” ino=15109 scontext=u:r:root_channel:s0 tcontext=u:object_r:dalvikcache_data_file:s0 tclass=file permissive=0

现在我们来分解一下这段日志每一小节的含义

  • <5>:kernel的日志等级
  • [ 27.706805]:发生的时间
  • (3):CPU数
  • [304:logd.auditd]:问题发生在audit
  • type=1400 : SYSCALL
    type=AVC - for kernel events
    type=USER_AVC - USER版本
  • audit(1420041991.220:17) : audit(时间:序列号)
  • avc: denied { execute }:字段取决于正在审核的事件类型。
  • pid=2182 comm=“app_process” :如果是任务,则记录进程ID以及执行文件的名称
  • path=“/data/dalvik-cache/arm64/system@framework@boot.oat” dev=“mmcblk0p18” ino=15109:目标信息
  • permissive: permissive (1) or enforcing (0)

分解出来后,我们就可以简单翻译成:在enforcing模式下,auditd执行app_process的execute事件发生权限错误,PID是2182。

基本分析流程

  1. 将SELinux 调到 permissive mode,然后一次性抓取出所有的"avc:" 的LOG。
  • 如果问题与开机流程无关,并且eng 版本能够复现。
    adb shell setenforce 0
  • 如果问题与开机流程相关,或者只有user build 能够复现。参考?“”“”设置permissive mode
  1. 确认访问是否是必须的?是否是违法恶意访问?
  2. 如果是正常访问,确认访问的目标类型是否太过广泛,如果太过广泛,则需要细化具体的文件目标。
  3. 添加对应的SELinux Policy 到对应的Policy 文件。

如何处理与Google 定义neverallow 冲突

其实对于这一点只要记住一个关键点,谷歌禁止的绝对不要在原文件进行修改,如果一定要修改其权限请重新创建一个process domain进行对节点的申请

配置路径

  1. 对于系统本身SEpolicy,并且在所有版本中都可以获取的,我们放在device/mediatek/sepolicy/base
  2. 对于debug版本申请的SEpolicy,我们放在device/mediatek/sepolicy/debug
  3. 对于三方vendor申请的SEpolicy,放在device/mediatek/sepolicy/third_party
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值