概述

SELinux 提供了三个用于设置和恢复文件安全上下文(context)的工具。虽然它们功能相似,但使用场景和底层实现有所不同。

工具类型主要用途
setfiles底层 C 程序直接根据 spec 文件设置文件标签
restoreconsetfiles 的封装恢复文件到默认安全上下文
fixfilesShell 脚本系统级别的批量修复工具

详细对比

setfiles

位置: /sbin/setfiles

特点:

  • 底层工具,直接操作文件上下文
  • 需要显式指定 file_contexts 配置文件
  • 功能最原始,性能最高
  • 输出详细,适合调试

常用选项:

setfiles [-F] [-R] [-v] [-n] [-e DIR] spec_file pathname...
选项说明
-F强制恢复,不检查文件类型是否匹配
-R递归处理目录
-v显示详细信息
-n干跑模式,不实际修改
-e DIR排除目录

使用场景:

# 容器内给另一个根文件系统打标签(你的使用场景)
setfiles -R -v /etc/selinux/targeted/contexts/files/file_contexts /mnt/rootfs

# 检查但不实际修改
setfiles -n -v file_contexts /path/to/check

# 排除某些目录
setfiles -R -e /proc -e /sys file_contexts /

restorecon

位置: /sbin/restorecon

特点:

  • setfiles 的友好封装
  • 自动使用当前策略的 file_contexts
  • 更安全的默认行为
  • 日常维护的首选工具

常用选项:

restorecon [-i] [-f filelist] [-R] [-r] [-v] [-n] pathname...
选项说明
-i忽略不存在的文件
-f filelist从文件读取路径列表
-R, -r递归处理
-v显示修改的文件
-F强制恢复
-n干跑模式

使用场景:

# 恢复单个文件
restorecon -v /etc/httpd/conf/httpd.conf

# 递归恢复目录
restorecon -Rv /var/www/html

# 从文件列表批量恢复
restorecon -f filelist.txt -v

# 检查但不修改
restorecon -n -Rv /path

与 setfiles 的区别:

  • restorecon 自动查找策略文件,setfiles 需要显式指定
  • restorecon 有更多安全检查
  • restorecon 是用户友好的工具

fixfiles

位置: /usr/sbin/fixfiles

特点:

  • Shell 脚本,调用 setfiles 或 restorecon
  • 用于系统级别的维护
  • 支持全系统 relabel
  • 创建 /.autorelabel 触发启动时重标签

语法:

fixfiles [-F] [-y] check | restore | verify | relabel
fixfiles [-F] [-y] [-R rootdir] [dir...]
命令说明
check检查文件上下文是否正确
restore恢复文件上下文
verify验证并报告差异
relabel创建 /.autorelabel 并重启

使用场景:

# 检查整个系统
fixfiles check

# 恢复整个系统
fixfiles restore

# 强制恢复(不提示)
fixfiles -F restore

# 对特定目录操作
fixfiles -R /mnt/rootfs restore

# 创建 autorelabel(重启时全系统重标签)
fixfiles relabel
# 或手动
touch /.autorelabel && reboot

内部逻辑:

# fixfiles 本质上是封装
fixfiles restore
# 等价于:
# 1. 检查 /selinux/member 或 /sys/fs/selinux/enforce
# 2. 临时设置 SELinux 为 permissive
# 3. 调用 setfiles -R -c policy file_contexts /
# 4. 恢复 SELinux 模式

核心区别总结

架构关系

┌─────────────────────────────────────────────────────────┐
│                    fixfiles (Shell)                      │
│  系统级维护工具                                          │
└───────────────────┬─────────────────────────────────────┘
                    │ 调用
                    ↓
┌─────────────────────────────────────────────────────────┐
│              restorecon (setfiles 封装)                  │
│  用户友好工具                                            │
└───────────────────┬─────────────────────────────────────┘
                    │ 调用
                    ↓
┌─────────────────────────────────────────────────────────┐
│                   setfiles (C 程序)                      │
│  底层工具                                                │
└─────────────────────────────────────────────────────────┘

功能对比表

特性setfilesrestoreconfixfiles
层级底层 C 程序封装工具Shell 脚本
配置文件需要显式指定自动查找自动查找
递归-R-R/-r默认递归
干跑模式-n-n-n (部分)
批量文件列表不支持-f filelist不支持
排除目录-e DIR不支持内置排除
全系统 relabel支持支持专用命令
输出详细度详细中等简洁
容器友好度✅ 最佳✅ 良好⚠️ 一般
跨根文件系统✅ 支持⚠️ 需要额外参数⚠️ 需要额外参数

使用场景推荐

容器内给另一个根文件系统打标签

你的场景: 在容器内给另一个根文件系统打标签

推荐: setfiles

# 挂载目标根文件系统
mount /dev/sdX /mnt/rootfs

# 方法1: setfiles (最直接)
setfiles -R -v \
  /etc/selinux/targeted/contexts/files/file_contexts \
  /mnt/rootfs

# 方法2: restorecon (需要额外参数)
restorecon -Rv -r /mnt/rootfs

# 方法3: fixfiles (如果目标系统有完整支持)
fixfiles -R /mnt/rootfs restore

为什么 setfiles 最适合容器场景:

  1. 不依赖目标系统的 SELinux 状态
  2. 可以显式指定 spec 文件路径
  3. 不检查当前策略是否加载
  4. 性能最好,开销最小

日常维护

场景: 恢复单个文件或目录的标签

推荐: restorecon

# 恢复新创建的文件
restorecon -v /new/file

# 恢复整个目录树
restorecon -Rv /var/www

系统级修复

场景: SELinux 策略更新后全系统重标签

推荐: fixfiles

# 检查需要修复的文件
fixfiles check

# 全系统恢复
fixfiles -F restore

# 或者触发启动时重标签
touch /.autorelabel
reboot

常见问题

1. 为什么 setfiles 在容器中更可靠?

# restorecon 可能失败的情况:
restorecon -Rv /mnt/rootfs
# 错误: 无法读取 /sys/fs/selinux/enforce (容器中可能不存在)
# 错误: 无法确定当前策略

# setfiles 绕过这些检查:
setfiles -R -v file_contexts /mnt/rootfs
# 直接读取 spec 文件并应用,不检查运行时状态

2. 什么时候需要 -F (force)?

# 当文件类型不匹配但你知道这是正确的
# 例如:普通文件需要 labeled 为 usr_exec_t
setfiles -F -v file_contexts /path/to/file

3. 如何验证结果?

# 查看文件上下文
ls -Z /path/to/file
# system_u:object_r:etc_t:s0   /path/to/file

# 对比预期上下文
matchpathcon /path/to/file
# /path/to/file    system_u:object_r:etc_t:s0

实际例子

容器构建场景

#!/bin/bash
# 在 Dockerfile 或构建脚本中

# 安装 SELinux 工具
yum install -y policycoreutils selinux-policy-targeted

# 挂载要打标签的文件系统
mount /dev/sdX1 /mnt/target

# 使用 setfiles 批量打标签
setfiles -R -v \
  /etc/selinux/targeted/contexts/files/file_contexts \
  /mnt/target

# 验证关键文件
ls -Z /mnt/target/usr/sbin/sshd

修复问题文件

# 发现某个服务无法启动,审计日志显示 context 问题
ausearch -m AVC -ts recent | audit2allow -w

# 检查当前上下文
ls -Z /etc/myapp/config.conf
# root:object_r:user_home_t:s0   /etc/myapp/config.conf

# 恢复正确上下文
restorecon -v /etc/myapp/config.conf
# root:object_r:etc_t:s0        /etc/myapp/config.conf

参考资料

  • man setfiles
  • man restorecon
  • man fixfiles
  • SELinux Policy Configuration: /etc/selinux/*/contexts/files/file_contexts