Annan 2023年09月11日

1.历史背景

在 SELinux 出现之前,Linux 上的安全模型叫 DAC,全称是 Discretionary Access Control,翻译为自主访问控制。

DAC 的核心思想很简单,就是:进程理论上所拥有的权限与执行它的用户的权限相同。比如,以 root 用户启动 Browser,那么 Browser 就有 root 用户的权限,在 Linux 系统上能干任何事情。

显然,DAC 管理太过宽松,只要想办法在 Android 系统上获取到 root 权限就可以了。那么 SELinux 是怎么解决这个问题呢?在 DAC 之外,它设计了一种新的安全模型,叫 MAC(Mandatory Access Control),翻译为强制访问控制。

MAC 的理论也很简单,任何进程想在 SELinux 系统上干任何事情,都必须在《安全策略文件》中赋予权限,凡是没有出现在安全策略文件中的权限,就不行。

关于 DAC 和 MAC,可以总结几个知识点:

  1. Linux 系统先做 DAC 检查。如果没有通过 DAC 权限检查,则操作直接失败。通过 DAC 检查之后,再做 MAC 权限检查
  2. SELinux 有自己的一套规则来编写安全策略文件,这套规则被称之为 SELinux Policy 语言。

2. Secure Context

在 Android系统中,所有对象大致可以分为两类:

  • 一种是的(文件、端口、系统属性等被调用对象),例如:u:object_r:proc:s0
  • 一种是的(进程、App等调用资源的对象),例如:u:r:vendor_init:s0

此处的 死 和 活 是一种比喻,映射到软件层面的意思是:进程能发起动作,例如它能打开文件并操作它。而文件只能被进程操作。

根据 SELinux 规范,完整的 Secure Context 字符串为:user:role:type[:range]

2.1 进程的 Secure Context

在 SELinux 中,每种东西都会被赋予一个安全属性,官方说法叫做 Security Context,Security Context 是一个字符串,主要由三个部分组成,例如 SEAndroid 中,进程的 Security Context 可通过 ps -Z 命令查看:

rk3288:/ $ ps -AZ
u:r:hal_wifi_supplicant_default:s0 wifi      1816     1   11388   6972 0                   0 S wpa_supplicant
u:r:platform_app:s0:c512,c768  u0_a14        1388   228 1612844  57396 0                   0 S android.ext.services
u:r:system_app:s0              system        1531   228 1669680 119364 0                   0 S com.android.gallery3d
u:r:kernel:s0                  root           582     2       0      0 0                   0 S [kworker/1:2]
u:r:radio:s0                   radio          594   228 1634876  89296 0                   0 S com.android.phone
u:r:system_app:s0              system         672   228 1686204 141716 0                   0 S com.android.settings
u:r:platform_app:s0:c512,c768  u0_a18         522   223 1721656 152116 0                   0 S com.android.systemui

上面的最左边的一列就是进程的 Security Context,以第一个进程 wpa_supplicant 为例

u:r:hal_wifi_supplicant_default:s0

其中:

  • u 为 user 的意思,SEAndroid 中定义了一个 SELinux 用户,值为 u
  • r 为 role 的意思,role 是角色之意,它是 SELinux 中一个比较高层次,更方便的权限管理思路。简单点说,一个 u 可以属于多个 role,不同的 role 具有不同的权限。
  • hal_wifi_supplicant_default 代表该进程所属的 Domain 为 hal_wifi_supplicant_default。MAC(Mandatory Access Control)强制访问控制 的基础管理思路其实是 Type Enforcement Access Control(简称TEAC,一般用TE表示),对进程来说,Type 就是 Domain,比如 hal_wifi_supplicant_default 需要什么权限,都需要通过 allow 语句在 te 文件中进行说明。
  • s0 是 SELinux 为了满足军用和教育行业而设计的 Multi-Level Security(MLS)机制有关。简单点说,MLS 将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问

2.2 文件的 Secure Context

文件的 Secure Context 可以通过 ls -Z 来查看,如下

rk3288:/vendor/lib $ ls libOMX_Core.so -Z
u:object_r:vendor_file:s0 libOMX_Core.so
  • u:同样是 user 之意,它代表创建这个文件的 SELinux user
  • object_r:文件是死的东西,它没法扮演角色,所以在 SELinux 中,死的东西都用 object_r 来表示它的 role
  • vendor_file:type,和进程的 Domain 是一个意思,它表示 libOMX_Core.so 文件所属的 Type 是 vendor_file
  • s0:MLS 的等级

3. TE规则

根据SELinux规范,完整的规则相关的语句格式为:

rule_name source_type target_type:class perm_set

  • rule_name 规则名
    • allow: 允许主体对客体进行操作
    • neverallow:拒绝主体对客体进行操作
    • dontaudit: 表示不记录某条违反规则的决策信息
    • auditallow:记录某项决策信息,通常 SElinux 只记录失败的信息,应用这条规则后会记录成功的决策信息
  • source_type 主体
    • Domain:一个进程或一组进程的标签。也称为域类型。允许用户自定义。
  • target_type 客体
    • Type:一个对象(例如,文件、套接字)或一组对象的标签。允许用户自定义。
  • class 类别
    • 要访问的对象的类型,例如文件、套接字等
    • system/sepolicy/private/security_classes中被定义
  • perm_set 动作集
    • 要执行的操作,例如读取、写入等。每个class有自己被定义的perm_set
    • system/sepolicy/private/access_vectors中被定义

下面结合例子说明一下:

# 允许user域中的进程 读取 script标签中的file类型文件 allow user script:file {read};
# 不允许user域中的进程 写入 script标签中的file类型文件 neverallow user script:file {write};

source_typetarget_type使用typetypeattributeattribute定义。

**attribute定义一个代表具有某种相中属性的集合(即域)。

attribute dev_type;

type定义代表一个或一类资源类型,并分配至不同属性(域)中。

# 定义一个类型,属于dev_type属性
type ttyMT_device, dev_type; 

以上定义可以拆分为两部分

# 仅定义一个类型
type ttyMT_device;
# 仅把ttyMT_device类型关联到dev_type属性
typeattribute ttyMT_device dev_type;

属性间使用逗号,一个类型可以关联至多个属性

type oem_lock_service, system_api_service, system_server_service, service_manager_type;

class字段使用comm和class定义,comm定义的class可以被class定义的对象继承。

common file {
 ioctl read write create getattr setattr lock relabelfrom relabelto
 append unlink link rename execute swapon quotaon mounton
}

class类型继承comm类型

class dir
inherits file
{
 add_name
 remove_name
 reparent
 search
 rmdir
 open
 audit_access
 execmod
}

contexts文件

contexts文件里定义了系统中所有的secure context。有如下的典型定义:

file_contexts //系统中所有file_contexts
seapp_contexts //app
property_contexts //属性
service_contexts    //SA服务
genfs_contexts //虚拟文件系统

以上提到过的,linux系统中一切都有个安全属性定义,即secure context。这一切定义都在context文件中。当新增一个进程时,往往要在这里定义相关服务或文件的context(标签)。深入实例,查看509selinux问题记录中neverallow的问题解决方案。

参考文档:

相关笔记

  • 509selinux问题记录
  • 鸿蒙配置文件