###

4. 编写第一个域策略:类型声明、属性定义、初始sid映射

本章将带领你完成SELinux域隔离策略的奠基工作——通过类型声明、属性定义与初始安全标识符(initial sid)映射,在策略数据库中为应用程序创建一个独立的“执行域”。这是编写任何自定义域策略的第一步,也是最关键的一步。

4.1 核心概念与作用

域(Domain)本质上是运行进程的安全上下文中的类型(Type)。为了让内核能区分该域与其他域,我们需为它声明一个独一无二的类型,并通过属性(Attribute)将域分组成可管理的集合。

要素 作用 示例语法结构
类型声明 定义一个新的对象/主体类型,作为域的标识符 type myapp_t;
属性定义 为类型赋予分类标签,便于规则批量授权 attribute domain; → typeattribute myapp_t domain;
初始sid映射 将启动阶段的安全上下文与类型关联,确保进程进入正确域 sid myapp_sid → sid myapp_sid myapp_t:myapp_r:myapp_t:s0
第一个域策略的三要素协同关系 类型声明 type myapp_t; 属性定义 typeattribute myapp_t domain; 初始sid映射 sid myapp_sid 策略加载后,内核通过sid映射将进程上下文中的 系统类型替换为自定义类型 myapp_t,完成域隔离

4.2 类型声明

类型是SELinux强制访问控制(MAC)的最基本单元。对于自定义应用域,我们遵循 应用名_t 的命名惯例。

  • 位置:在策略源文件 myapp.te(或相应的类型声明文件)中。
  • 格式:type 类型名称 [别名列表] [, 属性列表];

示例声明(单行)

type myapp_t;
type myapp_exec_t, file_type, exec_type;

该声明定义了两个类型:myapp_t 作为进程域,myapp_exec_t 作为可执行文件类型,后者同时加入了 file_type 和 exec_type 属性。

4.3 属性定义与关联

属性(Attribute)是类型的分类集合。通过将域类型加入 domain 属性,可以继承内核预置的进程管理授权。

  1. 定义属性:attribute myapp_domain;(自定义属性可选)。
  2. 关联类型:typeattribute myapp_t domain, myapp_domain;。
  3. 属性粒度:domain 属性用于所有进程域,unconfined_domain_type 用于不受限制域,参考以下典型属性清单:
属性名 用途 示例关联类型
domain 标记可执行进程的类型 init_t, unconfined_t, myapp_t
unconfined_domain_type 标记几乎无限制的域 unconfined_t
file_type 标记文件系统的对象类型 etc_t, usr_t, myapp_exec_t
exec_type 标记可执行文件类型 bin_t, myapp_exec_t

💡 使用 seinfo -tmyapp_t -x 可查询已加载策略中某个类型关联的所有属性。编写阶段用 grep 搜索 typeattribute 语句检查完整性。

4.4 初始sid映射

初始安全标识符(Initial SID)是系统启动阶段分配的安全上下文占位符。对于自定义服务,需要:

  1. 声明 SID:在 myapp.sid 文件中写入 sid myapp_sid。
  2. 映射安全上下文:在 myapp.sid 中追加一行映射规则:sid myapp_sid myapp_t:myapp_r:myapp_t:s0。
  3. 确保上下文完整性:myapp_r 角色需与域类型关联,s0 为默认多级安全(MLS)级别。
# myapp.sid 文件内容
sid myapp_sid
sid myapp_sid myapp_t:myapp_r:myapp_t:s0

⚠️ 若省略初始sid映射,系统启动时无法为该进程分配正确的安全上下文,可能导致进程运行在 unconfined_t 域,导致隔离失效。此外一定要确保角色 myapp_r 已通过 role myapp_r; 声明,并授权给域。

4.5 调试与验证实战

编写完成后,使用以下命令验证策略文件的正确性:

# 编译策略模块
make -C /usr/share/selinux/mcs -f /usr/share/selinux/mcs/include/Makefile myapp.pp
# 检查类型声明
seinfo -tmyapp_t -x
# 输出应显示关联属性:domain, file_type 等
# 验证sid映射(仅限重新加载完整策略时)
seinfo -smyapp_sid -x

如果编译出错,常见原因包括:

  • 类型未声明就引用——在 .te 文件中缺少 type myapp_t;。
  • 属性未定义——使用了自定义属性但未用 attribute 声明。
  • sid映射角色未定义——myapp_r 未在角色声明文件中定义。
  • 上下文格式错误——myapp_t:myapp_r:myapp_t:s0 中类型、角色、级别顺序必须严格对应。

4.6 稳定性与性能考量

  • 属性数量控制:每个类型关联10个以内属性,避免策略查询路径膨胀。
  • sid映射唯一性:每个custom sid映射仅对应一个安全上下文,不要重复定义。
  • 分区编译:将类型声明、属性关联、sid映射分别放入 myapp.te、myapp.if、myapp.sid,便于模块化调试。