SELinux 学习总结

什么是SELinux

SELinux 即Security-Enhanced Linux, 是一套强制性安全审查机制,Linux Kernel 2.6 版本后, 有直接整合进入SELinux, 搭建在Linux Security Module(LSM)基础上

SELinux 基本架构与原理.

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 的整体结构如下图所示:
整体流程图
SELinux 包含五个基本组成:

  • 用于处理文件系统的辅助模块, 即SELinuxFS.
  • 集成Linux Security Modules 的hooks sets.
  • Security Policy Database.
  • Security Label 验证模块.
  • Access Vector Cache (AVC), 访问向量缓存,以便提高验证速度.

基本的访问流程如下图所示:
访问流程图
流程如下:

  • 进程通过系统调用(System Call) 访问某个资源, 进入Kernel 后, 先会做基本的检测, 如果异常则直接返回.
  • Linux Kernel DAC 审查, 如果异常则直接返回.
  • 调用Linux Kernel Modules 的相关hooks, 对接到SELinux 的hooks, 进而进行MAC 验证, 如果异常则直接返回.
  • 访问真正的系统资源.
  • 返回用户态, 将结构反馈.

DAC(Discretionary Access Control):自主访问控制,基于“用户-用户组-其他/读-写-执行”的权限检查,进程理论上所拥有的权限与执行它的 用户的权限相同,该管理过于宽松,如果获得 root 权限,可以在 Linux 系统内做任何事情。
MAC(Mandatory Access Control):强制访问控制,基于安全上下文和安全策略的安全机制,用于补充 DAC 检查。访问系统资源时,会先进行 DAC 检查,DAC 检查通过,才能进行 MAC 检查,如果 MAC 检查通过,才能获得资源访问权限。SELinux 是 MAC 机制的一种实现

Core SELinux Components

SELinux 的核心组件可以参考下面的图:
SELinux 核心组件

  • Subject 通常是指触发访问行为的对象, 在Linux 里面通常是一个进程(Process).
  • Object Manager 即是对象访问管理器, 即可以知道Subject 需要访问哪些资源,并且触发验证机制
  • Security Server 即安全服务器, 用来验证某个Subject 是否可以真正的访问某个Object, 而这个验证机制是基于定义好的Security Policy.
  • Security Policy 是一种描述SELinux Policy 的语言.
  • Access Vector Cache (AVC) 是访问缓存, 用来记录以往的访问验证情况, 以便提供效率,快速处理.
审查机制

SELinux 对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 机制.

TE中控制语句的格式:rule_name source_type target_type : class perm_set

  • rule: 控制类型, 分成两方面 allow 以及 audit
  • source_type:也叫subject,通常是domain。
  • Target_type: 代表请求的资源的类型
  • class perm_set: 代表对资源访问的操作

TE中的rule:

  • allow:赋予某项权限。
  • auditallow:audit含义就是记录某项操作。默认SELinux只记录那些权限检查失败的操作。 auditallow则使得权限检查成功的操作也被记录。注意,allowaudit只是允许记录,它和赋予权限没关系。赋予权限必须且只能使用allow语句。
  • dontaudit:对那些权限检查失败的操作不做记录。
  • neverallow:用来检查安全策略文件中是否有违反该项规则的allow语句

举个栗子:下面是谷歌原生策略中init.te中的一部分

# Create /data/property and files within it.
allow init property_data_file:dir create_dir_perms;
allow init property_data_file:file create_file_perms;

# Set any property.
allow init property_type:property_service set;

# init can only find the APEX service
neverallow init { service_manager_type -apex_service }:service_manager { find };
# init can never add binder services
neverallow init service_manager_type:service_manager { add };
# init can never list binder services
neverallow init servicemanager:service_manager list;
Security Context

SELinux 给Linux 的所有对象都分配一个安全上下文(Security Context), 描述成一个标准的字符串。
两种类型

  • Subject 主体, linux通常以进程为单位
  • Object 访问对象, linux 通常以文件为单位
    标准格式
    user:role:type:[range]
  • User: 用户, 非Linux UID。android 只定义了一个user u
  • Role: 角色,一个user可以属于多个role,不同的role具有不同的权限。它是SELinux中一种比较高层次,更方便的权限管理思路,即Role Based Access Control(基于角色的访问控制,简称为RBAC, SELinux 不推荐使用)。android 只定义了一个role r,以及file system 使用object_r。因为user u 只有一个 role r, 所以没有进行角色访问约束(RBAC)。
  • Type: Subject或者Object的类型。 MAC的基础管理思路其实不是针对上面的RBAC,而是所谓的Type Enforcement Access Control(简称TEAC,一般用TE表示:根据Security Label 中的 type 进行权限审查, 审查 subject type 对 object type 的某个class 类型中某种permission 是否具有访问权限)。对进程来说,Type就是Domain。
  • Range: Multi-Level Security(MLS)的级别。MLS将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问。

如何查看文件的SELinux Context:ls -lZ
ls -lZ 查看文件的SELinux安全上下文
如何查看进程的SELinux Context: ps -Z 或者cat proc/PID/attr/current, 查看当前进程可用id
在这里插入图片描述
也可以使用ps -AZ,查看所有进程。

SELinux Mode

SELinux 分成两种模式, 即Permissve Mode(宽容模式), 和 Enfocing mode(强制模式).
Permissive Mode 只通过Kernel Audit System 记录LOG, 但不真正拦截访问.
Enforcing Mode 在记录LOG 的同时,还会真正的拦截访问.

查看SELinux 模式

  • 使用命令: adb shell getenforce
  • 通过AVC log 查看,在log结尾有 permissive=1/0 的标示: 1表示Permissive, 0表示Enforcing

切换SELinux模式

  • 使用命令: adb root; adb shell setenforce 0 (0表示Permissive模式, 1表示Enforcing模式),重启后失效
  • 修改init:修改system/core/init/SELinux.cpp文件里的IsEnforcing()函数,将该函数直接返回false

AVC log:
0181D <5> [ 94.720314][01-21 11:16:38.720] audit: type=1400 audit(1611198999.579:468): avc: denied { read } for pid=3949 comm=“ww6.temperature” name=“calibration” dev=“sysfs” ino=20396 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
ww6.temperature 进程缺少对标签为sysfs,类型为file,名称为calibration文件的 read权限

0057D <11> [ 2.746412][12-31 19:05:22.746] selinux: avc: denied { set } for property=ro.sf.lcd_width pid=1 uid=0 gid=0 scontext=u:r:vendor_init:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service permissive=0\x0a

AVC log说明:

  • <5> : kernel log level
  • [ 94.720314] [01-21 11:16:38.720]: kernel time
  • audit: log TAG 表示此log是通过audit打印的
  • type=1400: SYSCALL type=AVC - for kernel events type=USER_AVC - for user-space object manager events
  • audit(1611198999.579:468):audit(time:serial_number)
  • avc: denied: 表示当前操作被拒绝
  • { read } : 表示被拒绝的操作,{}中含有实际尝试的操作
  • for pid=3949 : 表示被拒的是一个进程,进程ID 3949
  • comm=“ww6.temperature” : 发生avc:denied的进程的进程名,即主体进程名
  • name=“calibration”: 尝试操作的目标文件或者目录的路径,即客体资源名称
  • dev=“sysfs” : 含有这个文件系统的设备节点,客体资源在该文件系统中
  • ino=20396 : 目标文件或目录的节点号
  • scontext=u:r:untrusted_app:s0 : 主体进程的安全上下文(例子中多了一个’:c512,c768’,说明了主体和客体安全级别不同(MLS规则))
  • tcontext=u:object_r:sysfs:s0: 客体资源的安全上下文
  • tclass=file:访问资源所属类别
  • permissive=0:当前是 Enforcing 模式,permissive=1 时为 Permissive 模式
SELinux 策略

SELinux 策略类型:(由于system image和vendor image的分离导致有了sepolicy的分离)

  • Public 公共策略(基础部分):导出的策略是非平台策略,开发人员可以在该策略上编写附加策略。类型和属性被版本化的策略包含在已交付的非平台策略中,非平台策略将与平台策略组合在一起。(定义的类型和属性system和vendor都可以使用)
  • Private 私有策略(基础部分):平台功能需要的策略,不会导出给其他供应商策略开发人员,因此可以假定不存在。(仅system image内部使用,只会编译到system image)
  • Vendor 供应商通用组件策略(外扩组件部分):供应商功能需要“仅供应商策略”。该政策可以参考公共政策,但不能参考私人政策。此策略适用于从核心/非供应商树生成并放置到供应商分区的组件。(只会编译到vendor image,能够引用到public目录下的定义并设置策略)

谷歌原生策略:

  • /system/sepolicy:谷歌原生策略,不要在此路径下进行修改
  • /system/sepolicy/private:谷歌原生 system 分区 private sepolicy
  • /system/sepolicy/public:谷歌原生 system 分区 public sepolicy
  • /system/sepolicy/vendor:谷歌原生 vendor 分区 sepolicy
  • /system/sepolicy/prebuilts:版本兼容 sepolicy

谷歌原生策略不能修改,我们可以修改平台的补充策略,各个平台策略存放位置有所不同。

安全上下文分类

安全上下文的描述文件一般是以xxx_contexts命名,可以在文件中为对象指定Security Context,具体分类如下:

  • file_contexts:用于为文件分配安全上下文
    eg: /system/bin/ims_bridged u:object_r:ims_bridged_exec:s0
  • property_contexts: 为Android系统属性分配上下文
    eg: vendor.bw.foreground.package u:object_r:system_prop:s0
  • genfs_contexts: 用于为不支持扩展属性的文件系统(例如,procvfat)分配上下文
    eg: genfscon proc /sprd_minidump/ u:object_r:proc_minidump_gesture:s0
  • seapp_contexts: 用于为应用进程和/data/data目录分配上下文
    eg: user=system seinfo=platform name=com.bw.engineermode domain=bwic_engineermode_app type=app_data_file levelFrom=user
问题实践

尝试解决上述avc log报出的权限问题:

  1. 在哪儿修改呢?
    scontext=u:r:untrusted_app:s0: log中主体进程上下文告诉了我们,因此我们应该要去修改untrusted_app.te(可以使用find命令查找一下,应该会出现很多,这时候我们要考虑修改哪个目录下的)
  2. 怎么修改?
    格式:allow scontext tcontext:tclass permission;
    allow untrusted_app sysfs:file {read open};
  3. 编译验证
    模块编译:mmm system/sepolicy/
    编译后会在out目录下生成两个目录:
    \vendor\etc\selinux
    \system\etc\selinux
    将这两个目录push到设备中重启后生效

编译验证时编译报错了:

libsepol.report_failure: neverallow on line 91 of system/sepolicy/private/coredomain.te (or line 32356 of policy.conf) violated by allow untrusted_app sysfs:file { read write open };
libsepol.report_failure: neverallow on line 95 of system/sepolicy/private/app_neverallows.te (or line 29605 of policy.conf) violated by allow untrusted_app sysfs:file { read write open };
libsepol.report_failure: neverallow on line 92 of system/sepolicy/private/app_neverallows.te (or line 29586 of policy.conf) violated by allow untrusted_app sysfs:file { write };
libsepol.report_failure: neverallow on line 514 of system/sepolicy/public/app.te (or line 9547 of policy.conf) violated by allow untrusted_app sysfs:file { write };
libsepol.check_assertions: 4 neverallow failures occurred

报错原因是被google用neverallow禁止了。Google 默认禁止app , 包括system app, radio app 等直接写/sys 目录以u:object_r:sysfs:s0 为标签的文件以及/proc 目录以u:object_r:proc:s0文件。如果直接放开SELinux 权限, 会导致CTS 无法通过

如何处理与Google 定义neverallow 冲突

当我们的权限被neverallow 后,我们不能直接去删掉neverallow ,会导致CTS无法通过,因此我们只能绕道,两种方式:

  • 通过system server service 或者 init 启动的service 读写操作, 然后app 通过binder/socket 等方式连接APP 访问. 此类安全可靠, 并且可以在service 中做相关的安全审查
  • 修改对应节点的SELinux Security Label, 为特定的APP,具体做法(以上述AVC报错为栗子):
    1. 参考原来的 sysfs 类型(type sysfs, fs_type, sysfs_type, mlstrustedobject;)定义一种新 type,
      在file.te中添加:type sysfs_xxx, fs_type, sysfs_type, mlstrustedobject;
    2. 使用新定义的 type 为目标文件配置安全上下文
      在file_context中添加:/xxx/xxx (目标文件路径) u:object_r:sysfs_xxx:s0
    3. 重新赋予主体进程访问新类型文件的权限
      在untrusted_app.te中添加:allow untrusted_app sysfs_xxx:file {read open};
新增属性配置安全上下文

Android 属性 property 在系统中存放在一块共享内存中,每个进程都能读,但是只有 init 进程能够写,请
求 init 进程帮助写属性值是需要 SELinux 权限的。
Android 属性名称前缀必须用 system\core\init\property_service.c 中定义的:

  • vendor 属性名前缀
  • persist.vendor.**
  • vendor.**
  • ro.vendor.**
    属性名不包含 vendor,则为系统属性。
    Android 11.0 属性标签有了更严格的限制,在 vendor 域属性所打的标签必须以 vendor_开头,否则会导致
    vts 测试失败。
    根据属性的命名规范,选择定义在 system 分区还是 vendor 分区,以 vendor 为例,新增属性步骤如下:
  1. 在 property.te 中添加属性的 type 定义。
    type vendor_xxx_prop, property_type;
  2. property_contexts 中对属性设定安全上下文。
    xxx.xxx. u:object_r:vendor_xxx_prop:s0
    xxx.xxx 后的“.”表示匹配以 xxx.xxx 开头的属性。
  3. xxx.te 文件中赋予对应进程访问该类型属性的权利。
    set_prop(xxx, vendor_xxx_prop)
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程简述  Android是目前最为流行的移动操作系统之一,它的开发涉及到多个知识领域。本课程将深入介绍Android系统启动过程中的重要组成部分——init进程,并探讨与之相关的多项关键技术。我们还将提供实际的开发案例,以RK3399开发板为例,通过演示Android产品配置、init启动流程、selinux权限管理、init.rc启动脚本定制等实际案例,让学员深入理解这些技术在实际产品开发中的应用场景和实现方法,提高学员的实际开发能力和经验,从而更好地应对实际产品开发中遇到的问题和挑战。知识运用方向学习Android启动方面的知识,可以参与如下实际开发工作项:启动流程定制: 根据产品需求调整Android启动流程,包括修改init.rc脚本、修改启动顺序和等待时间、加入自定义服务等。属性系统定制: 通过Android属性系统定制化启动流程,例如增加产品版本信息、定制开机音量等。日志系统分析: 掌握日志的捕捉、分析和排错技术,在启动过程中,需要加入调试信息来方便开发人员进行调试,同时需要进行日志的优化,避免日志输出过多占用过多的系统资源。selinux安全策略定制:在Android系统中,selinux是一种安全机制,用于保护系统的敏感资源和数据。在实际开发中,可能需要对selinux策略进行定制,以确保系统的安全性和稳定性。课程内容主要内容简述1, RK3399 开发板操作这部分内容重点介绍如何在FIreFly开发板上将Android 10系统运行起来, 包含编译FireFly的Android源码下载和编译, 镜像烧录运行,内核和模块编译,以及RK3399内核启动init进程的过程。2, 产品定制这部分讲解获取到方案商或者原厂提供的源码后, 如何定制一个新的产品,产品配置文件和模型, 原始代码中的配置文件和定制化东西3, Android日志代码编写之前讲过Android的日志系统, 并没涉及到代码编写, 这个部分重点讲解C/C++, java代码编写日志的API和代码4, 属性系统在Android中,属性使用的非常频繁的,可以用来作为进程间通信,也可以用于一些行为控制, 这个部分会重点介绍属性系统框架, API接口, 属性文件等知识点5,selinux进程对文件进行访问时,Android 4.3就开始集成了selinux权限管控, 如果需要启动某个脚本或者服务, selinux的配置就避免不了,并且Android8之后, Android系统对进程访问的权限管控的非常严格。6, init.rc脚本Android定义的一种脚本, 改脚本是有init进程启动, 是非常重要的一个脚本, 会包含系统中的其他很多脚本, 在我们系统开发时, 我们经常通过这个脚本进行一些定制化动作。7, init进程代码分析想要了解一个系统,就必须对源码进行分析和理解, 这个章节,带大家去跟读init进程代码, 这样,换了另外一个Android版本,完全就可以去读代码, 知道有什么变化。 

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值