SELinux 查错
- 内容
包含
enforcing
模式 SELinux 的系统可能会导致拒绝访问错误,从而导致应用程序无法正常运行。您可以使用audit2allow
或setroubleshoot
以用户友好的方式分析拒绝访问错误消息。- 原因
本文说明如何在不降低系统安全性的情况下解决 SELinux 导致的拒绝访问错误。
- 工作量
读完本文大约需要 30 分钟。
- 目标
您可以使用后文所述的工具之一来调试 SELinux 拒绝访问错误。
- 要求
一个正在运行的系统,其中已启用 SELinux。
1 /var/log/audit/audit.log
文件 #
默认情况下,如果 SELinux 是导致出错的原因,系统会将与此结果相关的日志消息发送到 /var/log/audit/audit.log
文件。
/var/log/audit/audit.log
如果您看到空的 /var/log/audit/audit.log
,这通常表示 auditd
服务未运行。在这种情况下,请执行以下步骤:
启动
auditd
服务:>
sudo
systemctl start auditd
使用以下命令在系统目标中启用该服务
>
sudo
systemctl enable auditd
/var/log/audit/audit.log
文件存储拒绝访问错误、服务事件等的消息。
在例 1: “/etc/audit/audit.log
中的示例行”中,可以看到 /var/log/audit/audit.log
内容的部分示例。
/etc/audit/audit.log
中的示例行 #type=DAEMON_START msg=audit(1348173810.874:6248): auditd start, ver=1.7.7 format=raw kernel=3.0.13-0.27-default auid=0 pid=4235 subj=system_u:system_r:auditd_t res=success type=AVC msg=audit(1348173901.081:292): avc: denied { write } for pid=3426 comm="smartd" name="smartmontools" dev=sda6 ino=581743 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir type=AVC msg=audit(1348173901.081:293): avc: denied { remove_name } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir type=AVC msg=audit(1348173901.081:294): avc: denied { unlink } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file type=AVC msg=audit(1348173901.081:295): avc: denied { rename } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582373 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file type=AVC msg=audit(1348173901.081:296): avc: denied { add_name } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir type=AVC msg=audit(1348173901.081:297): avc: denied { create } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file type=AVC msg=audit(1348173901.081:298): avc: denied { write open } for pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file type=AVC msg=audit(1348173901.081:299): avc: denied { getattr } for pid=3426 comm="smartd" path="/var/lib/smartmontools/smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file type=AVC msg=audit(1348173901.309:300): avc: denied { append } for pid=1316
日志中每条消息的外观如下:
type=AVC msg=audit(1348173901.081:299): avc: denied { getattr } for pid=3426 comm="smartd" path="/var/lib/smartmontools/smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
消息的每一行可分解为若干部分。例如,最后一行包含以下部分:
type=AVC
:每个 SELinux 相关审计日志行都以类型标识(例如
type=AVC
)开头。请注意,如果包含type=SYSCALL
的消息后接在类型不同但msg
值相同的消息后面,则它可能会提供有关事件的更多信息。msg=audit(1348173901.309:300)
:这是时戳,它是以纪元时间(自 1970 年 1 月 1 日开始经过的秒数)写入的。您可以针对纪元时间表示法中点号前面的部分使用
date -d
,以确定该事件是何时发生的:>
date -d @1348173901
Thu Sep 20 16:45:01 EDT 2012avc: denied { append }
:被拒绝的特定操作。在本例中,系统已拒绝将数据追加到文件。在浏览审计日志文件时,您可以看到其他系统操作,例如 write open、getattr 等。
for pid=1316
:发起操作的命令或进程的进程 ID
comm="rsyslogd"
:与该 PID 关联的特定命令
name="smartmontools"
:操作主体的名称
dev=sda6 ino=582296
:相关文件的块设备和 inode 编号
scontext=system_u:system_r:syslogd_t
:源环境,即操作发起者的环境
tclass=file
:主体的类标识
2 使用 audit2allow
分析 /var/log/audit/audit.log
#
您不必亲自解释 /var/log/audit/audit.log
中的事件,而可以使用 audit2allow
命令。
该命令可帮助您分析 /var/log/audit/audit.log
中晦涩难懂的日志消息。audit2allow
查错会话始终由三个不同的命令组成。首先,可以使用 audit2allow -w
-a
以更易于理解的方式显示审计信息。默认情况下,audit2allow -w -a
会处理 audit.log
文件。如果您要分析 audit.log
文件中的特定消息,请将其复制到临时文件,并使用以下命令分析该文件:
>
sudo
audit2allow -w -i FILENAME
>
sudo
audit2allow -w -i testfile
type=AVC msg=audit(1348173901.309:300): avc: denied { append } for pid=1316
comm="rsyslogd" name="acpid" dev=sda6 ino=582296
scontext=system_u:system_r:syslogd_t tcontext=system_u:object_r:apmd_log_t tclass=file
- 发生此问题的原因是:
缺少类型强制 (TE) 允许规则。
要生成可加载的模块以允许这种访问,请运行
>
sudo
audit2allow
要确定具体哪条规则拒绝了访问,您可以使用 audit2allow -a
显示已记录到 audit.log
文件中的所有事件中的强制规则,或使用 audit2allow -i FILENAME
显示应用于存储在特定文件中的消息的规则:
>
sudo
audit2allow -i testfile
#============= syslogd_t ==============
allow syslogd_t apmd_log_t:file append;
要创建您可以加载以允许先前被拒绝的访问的 SELinux 模块 mymodule
,请运行
>
sudo
audit2allow -a -R -M mymodule
如果您要对已记录到 audit.log
文件中的所有事件执行此操作,请使用 -a -M
命令参数。要仅针对特定文件中的特定消息执行此操作,请按下面的示例所示使用 -i -M
:
>
sudo
audit2allow -i testfile -M example
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i example.pp
如 audit2allow
命令所示,您现在可按以下方式运行此模块:使用 semodule -i
命令,后接 audit2allow
为您创建的模块的名称(在上例中为 example.pp
)。
3 使用 setroubleshoot
分析 AVC 消息 #
要以用户友好的方式分析 AVC 拒绝访问错误消息,可以使用 setroubleshoot
工具。
3.1 setroubleshoot
概览 #
3.1.1 什么是 setroubleshoot
? #
setroubleshoot
是可以从内核收集 SELinux 审计事件并对其进行分析的工具。如果发生此类事件,setroubleshoot
会通知管理员。
3.1.2 setroubleshoot
组件 #
SELinux 查错过程涉及以下组件,默认情况下,所有这些组件均已安装在 SUSE Linux Micro 上。
setroubleshoot-server
提供以下工具:setroubleshootd
- 用于处理传入请求和插件定义的主守护程序。该守护程序是按需激活的,不需要通过systemd
服务来运行。它只能由特权用户和专门的setroubleshoot
用户来管理。/var/lib/setroubleshoot/setroubleshoot_database.xml
文件中的警报数据库sealert
- 用于分析/var/log/audit.log
的命令行用户界面sedispatch
- 审计调度程序,用于扫描 SELinux AVC 消息并将其转换为 DBus 消息,然后将其传递给守护程序。
setroubleshoot-plugins
- 插件用于 AVC 消息分析,并提供有关如何解决问题的建议。
3.1.3 setroubleshoot
的工作原理 #
setroubleshoot
包含守护程序和分析插件。当插件检测到问题时,会向守护程序报告此问题,然后守护程序将检查这是否为已知问题。如果不是,则将新问题连同建议的解决方案一起添加到数据库中。
3.1.4 setroubleshoot
的优点 #
setroubleshoot
提供以下功能来帮助您解决 SELinux 安全系统上的问题:
发生 AVC 拒绝访问错误时向管理员发送警报。
自动分析 AVC 拒绝访问错误。
建议可能的修复方法,例如调整系统配置或安装更新等。
浏览以前的警报。
3.2 配置 setroubleshoot
#
尽管 setroubleshoot
的配置不需要调整,但在某些特殊用例中,您可能需要更改默认值。以下章节提供了一般用例。
setroubleshoot
的配置文件是 /etc/setroubleshoot
。通常,除了设置电子邮件通知之外,您无需修改其他配置。但是,如果您需要更改配置,可以编辑该文件,或使用 setroubleshootd
命令配置特定项目。命令语法如下:
#
setroubleshootd -c
SECTION.OPTION=VALUE
例如,要设置 from_address
选项,请运行如下命令:
#
setroubleshootd -c
email.from_address="example@mail.com"
3.2.1 配置 setroubleshoot
日志记录级别 #
默认日志记录级别(sealert_log
和 setroubleshootd_log
的值)设置为 warning
。但是,您可以将该值设置为下列其中一项:
- critical
仅记录导致系统无法正常运行的严重错误。
- error
报告可能影响系统的严重错误。
- warning
指出发生了意外情况,或者不久的将来可能会出现问题。但系统可按预期运行。
- info
记录确认系统正常运行的信息。
- debug
记录用于调试的详细信息。
3.2.2 配置 setroubleshoot
以发送电子邮件通知 #
如果系统中发生 AVC 拒绝访问错误,setroubleshoot
可向您发送电子邮件通知。
要获取这些通知,请执行以下步骤:
打开
/etc/setroubleshoot/setroubleshoot.conf
。在该文件中,根据需要调整以下配置项目:
- smtp_host
如果 SMTP 服务器未在本地主机上运行,请填写服务器地址。
- smtp_port
默认值为 25。通常不需要对此值进行任何调整。
- from_address
添加发件人地址。
- subject
配置所有邮件的通用主题。
- recipients_filepath
指定通知收件人列表的位置。
- use_sendmail
如果您使用 SendMail,请设置为
true
。
在
recipients_filepath
选项定义的路径(默认为/var/lib/setroubleshoot/email_alerts-recipients
)中创建邮件收件人文件。每个电子邮件地址必须独占一行。注释以 # 符号表示。
3.2.3 配置 setroubleshoot
数据库 #
可以更改 setroubleshootd
数据库中的记录数量、数据库位置或文件名前缀。
-
database_dir
指定数据库 XML 文件所在目录的绝对路径。
-
filename
配置数据库文件名的自定义前缀。然后,文件名如下所示:
FILENAME_PREFIX_database.xml
。-
max_alerts
定义数据库中的记录数上限。指定
0
表示记录数没有限制。-
max_alert_age
超过设置限制的警报将从数据库中删除。可使用以下单位:年、月、天、小时、分钟和秒,甚至可以使用复数形式;并且可以使用多个单位,例如
3 weeks 2 days
(相当于 23 天)。如果留空,则表示没有限制。
3.2.4 配置 setroubleshoot
以从远程服务器收集信息 #
可以配置 setroubleshoot
以从远程服务器收集 SELinux 审计数据。为此请配置地址列表。
- [listen_for_client] address_list
在服务器端。
- [client_connect_to] address_list
在客户端。
列表中的地址采用以下格式:
[{FAMILY}]ADDRESS[:PORT_NUMBER]
其中 {FAMILY} 为 {inet}
或 {unix}%{path}s
。如果地址族为 inet
,则您可以选择性地指定端口号,否则端口号将设置为 default_port
配置选项指定的默认值。默认值 {unix}%{path}s hostname
表示侦听本地 Unix 域套接字。
3.3 运行 /var/log/audit/audit.log
分析 #
要让 setroubleshoot
工具分析审计日志文件,请运行以下命令:
>
sudo
sealert -a /var/log/audit/audit.log
在以下示例输出中,有两个端口值已指派到 SSHD 服务:
100% done
found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------
SELinux is preventing sshd from name_bind access on the tcp_socket port 2222.
***** Plugin bind_ports (92.2 confidence) suggests ************************
If you want to allow sshd to bind to network port 2222
Then you need to modify the port type.
Do
# semanage port -a -t PORT_TYPE -p tcp 2222 1
where PORT_TYPE is one of the following: ssh_port_t, vnc_port_t, xserver_port_t.
***** Plugin catchall_boolean (7.83 confidence) suggests ******************
If you want to allow nis to enabled
Then you must tell SELinux about this by enabling the 'nis_enabled' boolean.
Do
setsebool -P nis_enabled 1
***** Plugin catchall (1.41 confidence) suggests **************************
If you believe that sshd should be allowed name_bind access on the port 2222 tcp_socket by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'sshd' --raw | audit2allow -M my-sshd
# semodule -X 300 -i my-sshd.pp
Additional Information:
...
First Seen 2024-02-07 14:26:27 UTC
Last Seen 2024-02-08 03:30:12 UTC
Local ID b5cbdd75-3f8d-425d-af75-f6cbf1540ffd
Raw Audit Messages
type=AVC msg=audit(1707363012.797:25): avc: denied { name_bind } for pid=841 comm="sshd" src=2222 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
Hash: sshd,sshd_t,unreserved_port_t,tcp_socket,name_bind
|
4 法律声明 #
版权所有 © 2006–2025 SUSE LLC 和贡献者。保留所有权利。
根据 GNU 自由文档许可证 (GNU Free Documentation License) 版本 1.2 或(根据您的选择)版本 1.3 中的条款,在此授予您复制、分发和/或修改本文档的权限;本版权声明和许可证附带不可变部分。许可版本 1.2 的副本包含在题为“GNU Free Documentation License”的部分。
有关 SUSE 商标,请参见 https://www.suse.com/company/legal/。所有其他第三方商标分别为相应所有者的财产。商标符号(®、™ 等)代表 SUSE 及其关联公司的商标。星号 (*) 代表第三方商标。
本指南力求涵盖所有细节,但这不能确保本指南准确无误。SUSE LLC 及其关联公司、作者和译者对于可能出现的错误或由此造成的后果皆不承担责任。