
SELinux 介绍和基本使用文章目录SELinux 介绍和基本使用1. SELinux 介绍1.1 SELinux 发展史1.2 SELinux 基础原理1.2.1 DAC 和MAC1.2.1.1 DAC1.2.1.2 MAC1.2.2 Core SELinux Components1.2.3 SELinuxMAC基本访问流程1.2.4 Security Context1.3 SELinux 语法1.3.1 关键词1.3.2 TE 部分1.3.3 SELinux 涉及到的文件1.4 SELinux in Qualcomm1.5 class1.6 权限缩写2. SELinux 使用2.1 AVC 报错解析2.2 调试2.2.1 临时关闭SELinux2.2.2 开机关闭SELinux2.2.3 代码关闭SELinux2.3 添加一个权限2.3.1 报错信息2.3.2 分析2.3.3 权限添加2.3.4 权限添加步骤2.4 添加一个新的label2.4.1 定义2.4.2 使用2.5 添加一个新的domian3. 附录3.1 The SELinux Notebook3.2 SELinux for Android 8.03.3 NB_SEforAndroid_13.4 80-PE644-7 - SELinux Overview and Update for Android O3.5 KBA-000000030298 - How to add a new domain for a new executable file and its policy for Android Q3.6 80-PN330-8 - SELinux Rules and CVE3.7 80-PJ388-21 - SELinux Overview3.8 KBA-200921030517 - quick build to verify sepolicy changes3.9 KBA-210521021443 - KBA list for Selinux3.10 SELinux 概念的直观解释3.11 Google 关于SELinux 的介绍和使用1. SELinux 介绍1.1 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 包含五个基本组成用于处理文件系统的辅助模块, 即SELinuxFS集成Linux Security Modules 的hooks setsSecurity Policy DatabaseSecurity Label 验证模块Access Vector Cache (AVC)访问向量缓存以便提高验证速度。SEAndroidAndroid 安全模型部分基于应用沙盒的概念。每个应用都在自己的沙盒内运行。在 Android 4.3 之前的版本中这些沙盒是通过为每个应用创建独一无二的 Linux UID在应用安装时创建来定义的。Android 4.3 及更高版本使用 SELinux 进一步定义 Android 应用沙盒的边界。作为 Android 安全模型的一部分Android 使用SELinux 对所有进程强制执行强制访问控制 (MAC)甚至包括以 Root/超级用户权限运行的进程Linux 功能。借助SELinuxAndroid 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、降低恶意软件的影响并保护用户免遭移动设备上的代码可能存在的缺陷的影响。SELinux 按照默认拒绝的原则运行任何未经明确允许的行为都会被拒绝。SELinux 可按两种全局模式运行宽容模式(Permissive mode)权限拒绝事件会被记录下来但不会被强制执行。强制模式(Enforcing mode)权限拒绝事件会被记录下来并强制执行。Android 中包含 SELinux处于强制模式和默认适用于整个 AOSP 的相应安全策略。在强制模式下非法操作会被阻止并且尝试进行的所有违规行为都会被内核记录到 dmesg 和 logcat 中。基于 Android 4.3宽容模式和 Android 4.4部分强制模式在 Android 5.0 及更高版本中已全面强制执行 SELinux。通过此项变更Android 已从对有限的一组关键域installd、netd、vold 和 zygote强制执行 SELinux 转为对所有域超过 60 个强制执行 SELinux。具体而言在 Android 5.x 及更高版本中所有域均处于强制模式。init 以外的任何进程都不应在 init 域中运行。出现任何常规拒绝事件对于 block_device、socket_device、default_service都表示设备需要一个特殊域。Android 6.0 通过降低策略的宽容度强化了系统安全从而实现更好的用户隔离和 IOCTL 过滤、降低可从设备/系统之外访问的服务面临的威胁、进一步强化 SELinux 域以及高度限制对 /proc 的访问。Android 7.0 更新了 SELinux 配置以进一步锁定应用沙盒并缩小受攻击面。此版本还将单片式mediaserver 堆栈拆分为较小的进程以缩小其权限范围。Android 8.0 更新了 SELinux 以便与 Treble 配合使用后者可将较低级别的供应商代码与 Android系统框架分离开来其中限制了System/Vendor 之间的交叉使用如VNDK 的权限控制就主要由selinux来控制。此版本更新了 SELinux 策略以允许设备制造商和 SOC 供应商更新自己的策略部分、构建自己的镜像vendor.img、boot.img 等然后更新这些镜像而不受平台影响反之亦然。虽然可以在设备上运行更高/更新版本的平台framework但反之并不成立供应商镜像(vendor.img/odm.img) 的版本不能高于平台 (system.img) 的版本。因此新平台可能会带来 SELinux 兼容性问题因为平台 SELinux 策略的版本要比该策略的供应商SELinux 部分更新。关于SEAndroid 部分可到附录中查阅SELinux for Android 8.01.2 SELinux 基础原理1.2.1 DAC 和MACDAC 即 Discretionary Access control自主访问控制即系统只提供基本的验证完整的访问控制由开发者自己控制。MAC 即 Mandatory Access control强制性访问控制即系统针对每一项访问都进行严格限制具体的限制策略由开发者给出。1.2.1.1 DACLinux DAC 采用了一种非常简单的策略将资源访问者分成三类分别是Owner、Group、Other。资源针对这三类访问者设置不同的访问权限。而访问权限又分成 read、write、execute。访问者通常是进程有自己的uid/gid通过uid/gid 和文件权限匹配来确定是否可以访问。将Root 权限根据不同的应用场景划分成许多的Root Capabilities其中如果有CAP_DAC_OVERRIDE 这项的话可以直接绕过Linux DAC限制。Linux DAC 有明显的不足其中一个重要点就是Root 权限 “无法无天”几乎可以做任意事情一旦入侵者拿到root 权限即已经完全掌控了系统。另外每一个进程默认都拿到对应这个用户的所有权限可以改动/删除这个用户的所有文件资源。很明显这个难以防止恶意软件。1.2.1.2 MACLinux MAC 针对DAC 的不足要求系统对每一项访问进行检查每访问一个文件资源都需要进行针对性的验证。而这个针对性的验证是根据已经定义好了的策略进行的。在Linux Kernel所有的MAC 机制都是搭建在Linux Security Modules (LSM) 基础上包括有SELinux、Apparmor、Smack 和 TOMOYO Linux等。针对Linux DACMAC 可以明显弥补DAC 的缺陷一方面限制Root 权限即使你有root 权限如果无法通过MAC 验证那么一样的无法真正执行相关的操作.。另外对每一项权限进行了更加完整的细化可限制用户对资源的访问行为。MAC 的两种形式Type Enforcement (TE)顾名思义Type Enforcement 是根据Security Label 中的type 进行权限审查审查subject type对object type 的某个class 类型中某种permission 是否具有访问权限是目前使用最为广泛的MAC审查机制简单易用。Multi-Level Security (MLS)多层安全机制是基于Bell-La Padula (BLP)模型将Subject 和 Object 定义成多层次的安全等级不同安全等级之间有相关的访问约束常见的访问约束是 “no write down” 和 “no read up”。它是根据Security Label 里面的最后一个字段label 进行确认的。目前在Android 中重点启用了Type Enforcement 机制Multi-Level Security (MLS) 虽然有定义但没有深入使用。1.2.2 Core SELinux Components图2 SELinux 核心组件Subject 通常是指触发访问行为的对象在Linux 里面通常是一个进程(Process)Object Manager 即是对象访问管理器即可以知道Subject 需要访问哪些资源并且触发验证机制Security Server 即安全服务器用来验证某个Subject 是否可以真正的访问某个Object而这个验证机制是基于定义好的Security PolicySecurity Policy 是一种描述SELinux Policy 的语言Access Vector Cache (AVC) 是访问缓存用来记录以往的访问验证情况以便提高效率快速处理。1.2.3 SELinuxMAC基本访问流程流程如下进程通过系统调用(System Call) 访问某个资源进入Kernel 后先会做基本的检测如果异常则直接返回Linux Kernel DAC 审查如果异常则直接返回调用Linux Kernel Modules 的相关hooks对接到SELinux 的hooks进而进行MAC 验证如果异常则直接返回访问真正的系统资源返回用户态将结果反馈1.2.4 Security ContextSELinux 给Linux 的所有对象都分配一个安全上下文(Security Context)描述成一个标准的字符串。SElinux 是一个标签系统。系统中的每个进程、每个文件/目录对象甚至每个网络端口、设备以及每个可能的主机名都会被打上一个标签所有操作都由标签控制。两种类型Subject 主体linux 通常以进程为单位Object 访问对象linux 通常以文件为单位如scontextu:r:system_app:s0标准格式user:role:type[:range]user用户非Linux UIDrole角色一个user 可以属于多个role不同的role 具有不同的权限。Android 中r 角色表示进程是活的能发起动作的角色object_r 这个角色是死的只能被人操作、访问一般是文件、设备、属性等typeSubject 或者Object 的类型。MAC 的基础管理思路是所谓的Type EnforcementAccess Control简称TEAC一般用TE 表示。对进程来说Type 就是Domain。在SEAndroid 中有一百多种typerangeMulti-Level SecurityMLS的级别。MLS 将系统的进程和文件进行了分级不同级别的资源需要对应级别的进程才能访问。通常格式为sensitivity[:category list][-sensitivity[:category list]]例如s0 - s15:c0.c1023其中s0 之后的内容可以不需要冒号后面的内容是categorysensitivity 和category 组合一起声明了当前的安全级别(security level)“-”号左右分别标识了安全级别的最低和最高这一列的参数将在MLS 约束检查时用到“15”、“1023”表示了sensitivity 和category 的最大值。如图5来自于高通文档的说明每一个对象都有一个Class比如一个文件它是File Class 类型每个Class 类型都会根据实际情况定义权限类型项如read、write、exec、ioctl、append 等等。Subject 即前面提到的主体它能够产生访问行为Linux 里面通常是一个process但process本身也可能是一个Object比如另外一个进程对它发送Signal去对它进行ptrace 操作。1.3 SELinux 语法1.3.1 关键词常用关键词allow赋予某项权限。dontaudit对那些权限检查失败的操作不做记录XTS 的bug 可能会用到。neverallow用来检查安全策略文件中是否有违反该项规则的allow 语句。1.3.2 TE 部分控制语句格式rule_name source_type target_type:class perm_setrule_name控制类型分成两方面 allow 以及 audit。source_type也叫subject通常是domain。target_type代表请求的资源的类型。class perm_set代表对资源访问的操作。如allow NetworkManager_t var_t:file read;1.3.3 SELinux 涉及到的文件file_contexts系统文件以及device 所对应的security context。格式regexp -type (security_contexts)如/opt/cvs(/.*)? u:object_r:cvs_data_t:s0 /mnt(/[^/]*)? -d u:object_r:mnt_t:s0 /dev/tts/[^/]* -c u:object_r:tty_device_t:s0 /etc/ppp(/.*)? -- u:object_r:pppd_etc_rw_t:s0regexp 是一个文件路径标签它提供了正则表达式格式的文件路径例如 /etc/init.d(/.*)?。 匹配文件路径可以提供安全上下文-type 是可选的可以留空。 当它被填充时它类似于 ls 命令的模式字段如-d 表示仅匹配目录-- 表示仅匹配文件genfs_contexts genfs 中的gen 为generalized 的意思用于为不支持扩展属性的文件系统例如proc 或 vfat分配标签一般对/目录proc 目录sysfs 等使用genfscon 关键词此配置会作为内核策略的一部分进行加载但更改可能对内核 inode 无效。如genfscon proc /asound/cards u:object_r:vendor_proc_audiod:s0 genfscon sysfs /devices/virtual/fts/touch_aoi u:object_r:vendor_sysfs_touch_aoi:s0hwservice_contexts声明HIDL service 安全上下文。如service_contexts用于为 Android Binder 服务分配标签以便控制哪些进程可以为相应服务添加注册和查找查询Binder 引用。在启动期间servicemanager 进程会读取此配置。如com.fingerprints.extension::IFingerprintSenseTouch u:object_r:hal_fingerprint_hwservice:s0 vendor.qti.hardware.alarm::IAlarm u:object_r:vendor_hal_alarm_qti_hwservice:s0property_contexts用于为 Android 系统属性分配标签以便控制哪些进程可以设置这些属性。在启动期间init进程会读取此配置。如power u:object_r:power_service:s0 android.os.UpdateEngineService u:object_r:update_engine_service:s0seapp_contexts用于为应用进程和 /data/data 目录分配标签。在每次应用启动时zygote 进程都会读取此配置在启动期间installd 会读取此配置。如vendor.sys.boot_mode u:object_r:vendor_boot_mode_prop:s0 vendor.sxr. u:object_r:vendor_sxr_prop:s0user_isolated domainisolated_app levelFromuser user_app seinfoapp_zygote domainapp_zygote levelFromuser user_app isPrivApptrue namecom.google.android.gsf domaingmscore_app typeprivapp_data_file levelFromuser user_app minTargetSdkVersion28 fromRunAstrue domainrunas_app levelFromallvndservice_contexts用于和vendor service 通信如mac_permissions.xml用于根据应用签名和应用软件包名称后者可选为应用分配 seinfo 标记。随后分配的 seinfo 标记可在 seapp_contexts 文件中用作密钥以便为带有该 seinfo 标记的所有应用分配特定标签。在启动期间system_server 会读取此配置。如wfdhdcpvndservice u:object_r:vendor_wfdhdcpvndservice_service:s0 DisplayFeatureControl u:object_r:DisplayFeatureControl_service:s0!-- Media key in AOSP -- signer signatureMEDIA seinfo valuemedia / /signer1.4 SELinux in Qualcomm关于Android 平台sepolicy 中private/public/vendor 三个文件夹的解释private: Elements defined in this folder is used by core domain only.public: Elements are packed into system image. They are exported to vendor domain.vendor: Elements are packed into vendor image.如果想知道知道system/sepolicy 和device/qcom/sepolicy*下哪些文件或文件夹参与编译可查看对应的mk 文件Android 平台在system/sepolicy/Android.mkQC 平台在device/qcom/sepolicy/SEPolicy.mk和device/qcom/sepolicy_vndr/SEPolicy.mk1.5 class定义路径system/sepolicy/private/security_classes如每个class 可允许的操作system/sepolicy/private/access_vectors如# file-related classes class filesystem class file class anon_inode class dir class fd class lnk_file class chr_filecommon file { ioctl read write create getattr setattr lock …… }1.6 权限缩写用一个字段代替若干个操作权限system/sepolicy/public/global_macros如define(x_file_perms, { getattr execute execute_no_trans map }) define(r_file_perms, { getattr open read ioctl lock map watch watch_reads }) define(w_file_perms, { open append write lock map }) define(rx_file_perms, { r_file_perms x_file_perms }) define(ra_file_perms, { r_file_perms append }) define(rw_file_perms, { r_file_perms w_file_perms })2. SELinux 使用2.1 AVC 报错解析type1400 audit(1642146837.807:73): avc: denied { read write } for commsensors.qti namediag devtmpfs ino27832 scontextu:r:vendor_sensors_qti:s0 tcontextu:object_r:vendor_diag_device:s0 tclasschr_file permissive0翻译上面avc 报错进程sensors.qti对”diag”进行操作类型为chr_file 的{ read write }操作被拒绝2.2 调试2.2.1 临时关闭SELinuxadb rootadb shell setenforce 0 [1打开]adb shell getenforce2.2.2 开机关闭SELinuxadb rootadb shell setenforce 0adb shell stopadb shell startNOTE:上述四步操作之后DUT 可能无法开机原因之一就是因为SELinux 被关闭导致有些进程有权限进行相关操作但由于缺少进程所依赖的资源导致进程无法启动进而无法启动Android。2.2.3 代码关闭SELinux在BoardConfig.mk 添加BOARD_KERNEL_CMDLINE androidboot.selinuxpermissive在system/core/init/selinux.cpp 中把is_enforcing 强制赋值为false原代码bool is_enforcing IsEnforcing();2.3 添加一个权限2.3.1 报错信息updater_engine: type1400 audit(0.0:1900): avc: denied { use } for path/storage/emulated/0/xxx.zip devsdcardfs ino10872 scontextu:r:update_engine:s0 tcontextu:r:mediaprovider_app:s0:c228,c256,c512,c768 tclassfd permissive02.3.2 分析从log 上看是update_engine 对mediaprovider_app 缺少fd 类型的use 权限对于上述avc 报错update_engine 的te 文件通常是在system/sepolicy 下device/qcom下也可能有还无法确定是要在哪个路径下添加这个权限可以看一下mediaprovider_app 对应的te 文件在哪并不是所有的文件可以直接添加权限在system/sepolicy 下定义的te它的范围仅限于system/sepolicy其他路径访问不到此题的mediaprovider_app.te 也在system/sepolicy 下其次还需要注意的是对于主体的update_engine.te在system/sepolicy 下除了public|private 下有之外还在prebuilts/api 下有很多那就说明不能只在public/private对应的update_engine.te添加权限还要在最新的prebuilts/api/xx.0/public|private/update_engine.te 添加权限2.3.3 权限添加在system/sepolicy 下添加权限在private/update_engine.te 下添加allow update_engine mediaprovider_app:fd use;在prebuilts/api/31.0/private/update_engine.te 添加相同语句allow update_engine mediaprovider_app:fd use;2.3.4 权限添加步骤确认主体和目标控制范围是在system/sepolicy 还是device/qcom 或者其他路径下确认主体te 文件是否在prebuilts/api 下也有确认上述两点后添加对应权限2.4 添加一个新的label2.4.1 定义如果是要访问文件可以在file_contexts 添加属性的话在property_contexts 添加如代码中需要获取手机中sys/bootinfo 路径下的内容需要在genfs_contexts 定义一个label 来指代这个路径给这个代码所属的进程或服务使用genfs_contextsgenfscon sysfs /bootinfo u:object_r:sysfs_bootinfo:s0然后需要给这个label 添class见security_classes具体定义了哪些操作类型表示这个label只能被这种类型的操作使用file.tetype sysfs_bootinfo, fs_type, sysfs_type;2.4.2 使用如果某个进程或服务需要访问手机中这个路径下的内容就在这个服务或进程的主体te 文件中添加相关操作只需要允许进程或服务访问定义的label 即可表示进程或服务可以访问手机中这个路径下的所有内容dumpstate.teallow dumpstate sysfs_bootinfo:file r_file_perms;2.5 添加一个新的domianInite.tetype init, domain, mlstrustedsubject; type init_exec, exec_type, file_type;allow init kernel:fd use; allow init { metadata_block_device misc_block_device recovery_block_device system_block_device userdata_block_device }:{ blk_file lnk_file } relabelto;file_contexts/init u:object_r:init_exec:s03. 附录3.1 The SELinux Notebookhttps://freecomputerbooks.com/books/The_SELinux_Notebook-4th_Edition.pdf3.2 SELinux for Android 8.0https://source.android.com/security/selinux/images/SELinux_Treble.pdf3.3 NB_SEforAndroid_1http://selinuxproject.org/page/NB_SEforAndroid_13.4 80-PE644-7 - SELinux Overview and Update for Android O3.5 KBA-000000030298 - How to add a new domain for a new executable file and its policy for Android Q3.6 80-PN330-8 - SELinux Rules and CVE3.7 80-PJ388-21 - SELinux Overview3.8 KBA-200921030517 - quick build to verify sepolicy changes3.9 KBA-210521021443 - KBA list for Selinux3.10 SELinux 概念的直观解释https://www.jianshu.com/p/115650a5bf413.11 Google 关于SELinux 的介绍和使用https://source.android.com/security/selinux/