SELinux引发audit2why异常:SCP上传/foo/bar权限拒绝问题排查
嘿,这个问题其实挺典型的——SELinux下交互式SSH登录创建文件和SCP非交互式上传的进程上下文(SELinux里的安全域)完全不一样,这就是核心差异所在。我给你一步步拆解排查和修复的方法:
1. 先抓完整的SELinux审计拒绝日志
别只依赖audit2why的简要输出,得拿到完整的事件细节才能精准定位问题:
- 先清空当前审计日志(避免旧日志干扰):
sudo truncate -s 0 /var/log/audit/audit.log - 再试一次那个失败的SCP上传操作
- 然后提取最近的SELinux访问控制拒绝事件:
sudo ausearch -m avc -ts recent
这条命令会输出所有刚发生的权限拒绝事件,里面会包含源进程的SELinux上下文、目标目录的上下文、被拒绝的具体操作这些关键信息——这些是排查的核心。
2. 对比两种场景的进程上下文差异
你说SSH登录后能创建文件,那先看看交互式会话的进程安全域:
- SSH登录服务器后,直接跑:
ps -Z -p $$
输出大概是unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023,这个unconfined_t是不受限的安全域,几乎拥有所有操作权限。
再看SCP进程的上下文(从刚才的ausearch输出里找comm="scp"的条目,看scontext字段),SCP的进程上下文一般是system_u:system_r:sshd_t:s0-s0:c0.c1023——也就是SSH服务的安全域sshd_t,SELinux对这个域的权限限制比unconfined_t严格得多。
这就是为什么交互式能创建,SCP不行的核心原因:两个操作的进程处于不同的SELinux安全域,权限规则不一样。
3. 检查目标目录的SELinux上下文
看看/foo/bar的SELinux标签:ls -Z /foo/bar
输出会类似unconfined_u:object_r:default_t:s0 /foo/bar,这里的default_t就是目录的安全类型。
SELinux的规则是:进程的安全域(比如sshd_t)必须拥有对目标资源安全类型(比如default_t)的对应权限(比如写、创建文件)才能操作。unconfined_t几乎不受限,所以能创建,但sshd_t可能没有这个权限。
4. 用audit2allow分析具体缺什么权限
把刚才ausearch的输出传给audit2allow,就能知道具体需要给sshd_t添加什么权限:sudo ausearch -m avc -ts recent | audit2allow -w
这个命令会直白地解释拒绝原因,比如:
type=AVC msg=audit(1234567890.123:456): avc: denied { add_name } for pid=1234 comm="scp" name="test.txt" dev="sda1" ino=789 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir
翻译过来就是:sshd_t域的SCP进程,被拒绝在default_t类型的目录下执行add_name(也就是创建文件)操作。
如果想直接生成修复用的规则模块,可以跑:sudo ausearch -m avc -ts recent | audit2allow -M myscp
5. 两种常见修复方式
方式一:调整目标目录的SELinux上下文(推荐,更符合SELinux最佳实践)
如果这个目录就是用来通过SSH传输文件的,把它的安全类型改成适合SSH操作的类型,比如ssh_home_t或者user_home_t:
# 添加上下文规则 sudo semanage fcontext -a -t ssh_home_t "/foo/bar(/.*)?" # 应用规则到目录 sudo restorecon -Rv /foo/bar
之后再试SCP,应该就能正常上传了。
方式二:创建自定义SELinux模块给sshd_t加权限
如果不想修改目录上下文,就用刚才生成的模块:
# 生成模块文件(myscp.te和myscp.pp) sudo ausearch -m avc -ts recent | audit2allow -M myscp # 加载模块 sudo semodule -i myscp.pp
这样就直接给sshd_t域添加了操作该目录的权限。
6. 额外检查:SELinux布尔值
有些SELinux布尔值会影响SSH相关操作,你可以看看有没有需要调整的:semanage boolean -l | grep ssh
比如allow_ssh_home_dirs、sshd_can_relabel这些,不过注意像sshd_full_access这种权限很大的布尔值,谨慎开启。
内容的提问来源于stack exchange,提问作者jgr208





