上一篇 SELinux 在管什么 把地图铺开:域、AVC、初始化、四段标签、TE allow。本文只挖一块地形——type_transition:进程(以及新建文件)的 Type 何时被改写、规则存在哪、和 allow 怎么配合。
仍默认 Fedora Targeted。若域 / 初始化 / TE 还不熟,先读概念文再回来。
适用读者
需要概念文里的底子,再加上一点「想看清服务域从哪来」的动机。
- 已读懂 SELinux 概念 中的域、初始化、TE、AVC。
- 知道
fork/execve:新程序映像是在 exec 时换上的。 - 不要求会写
.te;文末有只读查询命令即可跟上。
它解决什么问题
TE 的 allow 回答:当前 Type 能不能对另一 Type 做某操作。
默认创建/启动时,新对象的 Type 往往靠继承(子进程继承父域;新文件常继承父目录类型)。
type_transition 回答另一件事:在特定条件下,不要用继承默认,而强制落成策略指定的 Type。
服务要进 httpd_t、日志文件要落成某类 Type,靠的就是它(外加配套 allow)。
规则长什么样
策略语言里的基本形态:
type_transition 源类型 相关类型 : class 结果类型;
两类最常见。
进程域转换
type_transition 源域 可执行文件类型 : process 目标域;
概念例:
type_transition init_t httpd_exec_t:process httpd_t;
处在 init_t 的进程去 exec 类型为 httpd_exec_t 的文件时,新进程域默认为 httpd_t。
文件类型转换
type_transition 源域 父目录类型 : file 新文件类型;
某域在某类目录里创建文件时,新 inode 的默认 Type 由规则指定,而不是傻继承。dir、lnk_file 等 class 同理。
命名上常见 *_exec_t → *_t,这是惯例,不是内核写死的万能公式。叫什么 Type、从谁转到谁,都由策略决定。
表从哪里来
type_transition「表」不是另维护的 Excel,而是已加载 SELinux 策略里所有 type_transition 规则的集合。
定义路径:
- 策略源码(多为
.te)里写语句,或用宏(如domain_auto_trans)一次生成 transition + 一批 allow。 - 配
.fc:路径 → 默认文件标签(如/usr/sbin/httpd→httpd_exec_t)。 - 打成
.pp,经semodule -i或开机加载进内核。
发行版上这些在 selinux-policy-targeted 的各个策略模块里(semodule -l 可见 httpd、sshd、init 等)。
内核执行时查的是当前已加载策略;sesearch -T 查的也是这份。
和 allow 的关系:同属 TE(Type Enforcement) 机制,但是两类规则——transition 管「默认变成谁」,allow 管「允不允许这样及之后的操作」。
exec 换域逐步
以「systemd / init 相关域启动 httpd」为叙事(真实源域名因版本可能是 init_t 的变体,思想相同)。
父进程域: init_t(示意)
文件标签: /usr/sbin/httpd → httpd_exec_t
希望结果: 子进程 → httpd_t
收集键
execve 时内核拿到:
- 当前(旧)域
- 可执行文件的 Type
- class =
process
查 transition
找是否存在 type_transition 旧域 文件type : process 新域。
- 命中 → 候选新域 = 规则目标(如
httpd_t) - 未命中 → 候选新域 = 旧域(默认不换域)
再过 allow(TE)
transition 只回答「默认想变成谁」。还要有配套 allow,否则转换失败或 exec 被拒。常见相关包括:
| 方向 | 大致含义 |
|---|---|
旧域 → 文件 type:execute 等 |
能不能执行这个文件 |
旧域 → 新域:process 上的 transition |
允不允许从旧域转到新域 |
| 文件 type 作为新域的 entrypoint | 这个文件能不能当进入该域的入口 |
| Role 约束 | 当前 Role 是否允许关联目标域 |
成功换域 ≈ transition 命中 AND 相关 allow 通过 AND Role 等约束通过。
写入新进程
成功则新进程第三段变成目标域,例如 system_u:system_r:httpd_t:s0。之后一切 TE 检查按新域,不再按父域。
失败时 AVC 里常见 execute / transition / entrypoint 被拒——读法见概念文「名词解释 · AVC」。
Entrypoint 与 exec 类型
安全上不希望「任意 bin_t 被 exec 都能进 httpd_t」。
常见拆法:
- 二进制:
httpd_exec_t(入口) - 网页等内容:
httpd_sys_content_t(客体,不当乱入域的入口) - 运行域:
httpd_t
策略规定:只有特定入口类型配合 transition,才能进入对应域。
所以可执行文件的 Type 是 transition 的输入键,不是装饰性后缀。
和初始化的关系
概念文里的 SELinux 初始化与本文的关系:
| 会话初始化 | exec type_transition | |
|---|---|---|
| 时机 | 用户登录映射 | 某次 execve |
| 结果 | 会话初始域(如 unconfined_t) |
从旧域换到新域(如 httpd_t) |
| 典型谁 | 交互式 shell / 桌面会话 | systemd 拉起的 confined 服务 |
服务进程的「初始域」在实践中往往就是:父域 exec 入口文件 → type_transition → 服务域。
之后若再 exec 并命中其它规则,叫继续换域,不是又登录一次。
你在 unconfined_t 的 shell 里跑普通命令:很多没有指向其它域的 transition,于是一直停在原域——这是预期,不是 transition「坏了」。
文件 transition
创建文件时同构:键变成(进程域 × 父目录 Type × file/dir…),查 transition 得到新 inode 默认 Type,同样要配套 allow。
注意和运维命令的分工:
- type_transition:创建瞬间的默认类型
semanage fcontext+restorecon:按路径规定/修复标签,不是 exec 时那张 transition 表本身
策略模块里怎么写
人写策略时常见三件套(发行版已写好,此处仅帮助读懂):
# .te(概念)
type httpd_t;
type httpd_exec_t;
domain_auto_trans(init_t, httpd_exec_t, httpd_t); # 宏 ≈ transition + allow
# .fc
/usr/sbin/httpd -- system_u:object_r:httpd_exec_t:s0
加载进内核后,transition 表与 allow 表都来自这些模块。整套 SELinux 还可粗分为:内核裁决、用户态工具(semodule / restorecon / sesearch)、策略内容(targeted + 大量 .pp)——细节不必一次记完,知道「规则在策略模块里」即可。
本机怎么查
# 需要 setools-console(包名因发行版可能略异)
sudo dnf install setools-console
# 谁会 transition 到 httpd_t
sesearch -T -t httpd_t
# 某源域在 process 上的 transition
sesearch -T -s init_t -c process
# 某域作为主体的 allow(TE 权限表;结果很多,建议加 -c / -t)
sesearch -A -s httpd_t -c file
# 对照:文件类型 vs 进程域
ls -Z /usr/sbin/httpd
ps -eZ | grep httpd
读 AVC、真实拒绝案例见 Cursor Remote SSH 与 SELinux。
小结
- type_transition = 策略里的默认 Type 改写规则;由
.te/宏写入、经策略模块加载进内核 - allow = TE 的权限表;换域时与 transition 一起满足,不是二选一
- exec 换域键是(旧域 × 文件 Type);
*_exec_t常作 entrypoint,命名是惯例 - 无命中 transition → 多半继承旧域;服务进 confined 域通常靠命中 + allow
- 文件 transition 管创建默认类型;路径标签修复是另一条线
地图在 SELinux 在管什么;本文是换域这块地形。