我在 Fedora 20 机器上运行了一个服务,启动时会尝试使用 Avahi 注册服务。如果我的服务在 SELinux 处于宽容模式时启动,则此方法可完美运行,但当 SELinux 处于强制模式时,该服务将不会注册。
我知道httpd_dbus_avahi
SELinux 中的布尔值。这可以完美地允许 Apache 注册服务,但我找不到太多关于如何允许其他特定服务与 Avahi 通信的信息。
更具体地说,我试图允许 tvheadend 向 Avahi 注册其 HTSP 服务,但我也很好奇如何允许任何特定服务与 Avahi 通信而不会被 SELinux 阻止。我对关闭 SELinux 或允许想要与 Avahi 通信的进程不感兴趣。
编辑:添加了与 tvheadend 相关的所有 SELinux 和服务单元信息
---SELinux---
audit.log 消息
执行并重新启动 tvheadend 服务后semodule -DB
。以下是审计日志中出现的所有消息。最后一条消息似乎是问题所在,但我不确定该怎么做...
type=SERVICE_STOP msg=audit(1393282994.012:512): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg=' comm="tvheadend" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
type=SERVICE_START msg=audit(1393283083.635:513): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg=' comm="tvheadend" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
type=USER_AVC msg=audit(1393283084.291:514): pid=752 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.114 spid=731 tpid=14478 scontext=system_u:system_r:avahi_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=dbus exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=?'
过程
输出自ps -AZ | grep tvheadend
system_u:system_r:init_t:s0 2599 ? 00:00:06 tvheadend
我注意到init_t
进程类型似乎有点奇怪,因为我的系统上所有其他服务都具有该initrc_t
进程类型。我不确定为什么 tvheadend 服务在这方面有所不同。
用户
输出自sudo -u hts id
uid=1001(hts) gid=1003(hts) groups=1003(hts),39(video) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
我仅使用此用户来运行 tvheadend 服务。此用户的主目录位于比系统分区大得多的单独分区上,因为 tvheadend 生成的 DVR 文件可能会变得非常大。
当我创建此用户时,我没有使用--system
带有命令的开关useradd
。也许我应该这样做?
可执行文件
输出自ls -Z /usr/local/bin | grep tvheadend
-rwxr-xr-x. root root system_u:object_r:bin_t:s0 tvheadend
- -服务 - -
单元文件
[Unit]
Description=TVHeadEnd
After=syslog.target network.target avahi-daemon.service sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.demux0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.dvr0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.frontend0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.net0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.demux0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.dvr0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.frontend0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.net0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-vbi0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-vbi1.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-video0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-video1.device
Wants=sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.demux0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.dvr0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.frontend0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb0.net0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.demux0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.dvr0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.frontend0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-dvb-dvb1.net0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-vbi0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-vbi1.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-video0.device sys-devices-pci0000:00-0000:00:1c.0-0000:05:00.0-video4linux-video1.device
[Service]
Type=forking
GuessMainPID=no
EnvironmentFile=/etc/sysconfig/tvheadend
ExecStart=/usr/local/bin/tvheadend -f -u $TVH_USER -g $TVH_GROUP -p $TVH_PID -b $TVH_ADDRESS --http_port $TVH_HTTP_PORT --htsp_port $TVH_HTSP_PORT
PIDFile=$TVH_PID
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
单元环境文件
TVH_USER=hts
TVH_GROUP=hts
TVH_PID=/var/run/tvheadend.pid
TVH_ADDRESS=0.0.0.0
TVH_HTTP_PORT=9981
TVH_HTSP_PORT=9982
答案1
运行这项服务init_t
可能不是一个好主意。
你得到这种行为的原因是tvheadend
因为大概标记为bin_t
,并且不存在将此类文件移出上下文的转换规则init_t
。
你可以搜索一下来确定一下。
$ sesearch -s init_t --type -c process | grep bin_t
此命令未返回任何结果。进程未从 init_t 中转换出来bin_t
。
您还应避免运行此类型,initrc_t
因为它不适合该服务。事实上,一般来说——最好的解决方案是正确地为您的服务编写一个受限的策略,但这超出了本答案的范围。
相反,您需要将流程从 移出init_t
到另一种类型。由于此应用程序不存在策略,因此最好将其移入unconfined_t
,因为存在类型转换。
$ sesearch -s init_t --type -c process -t unconfined_exec_t
Found 1 semantic te rules:
type_transition init_t unconfined_exec_t : process unconfined_t;
我们还可以检查策略中正在被命中的规则是否不会被命中unconfined_t
(它不应该被命中)。
$ sesearch -s avahi_t -p send_msg -c dbus -t unconfined_t --allow
Found 2 semantic av rules:
allow avahi_t unconfined_t : dbus send_msg ;
allow system_bus_type unconfined_t : dbus send_msg ;
为此,只需将您的tvheadend
程序重新标记为unconfined_exec_t
。
semanage fcontext -a -t unconfined_exec_t -f f /usr/bin/tvheadend
然后恢复。
restorecon /usr/bin/tvheadend
现在,重新运行你的服务应该工作。如果你重新运行,ps -AZ | grep tvheadend
你会看到你的进程正在运行unconfined_t
。
理想情况下,应该为该程序使用一个新策略,但是如果不存在策略,最好在域中完全不使用策略来运行它unconfined_t
。initrc_t
并且init_t
并不是真正用于运行服务(尽管有些服务确实错误地进入其中),initrc_t
最初是为了运行 SYSV shell 脚本而init_t
设想的,用于运行 systemd/init 本身。
答案2
apache_selinux
可# semanage permissive
用于允许特定进程在宽容模式。
# semanage permissive -a avahi_t
我建议找一些关于其用法的更详细的信息
不过,找到一个比简单地“允许服务宽松”的访问控制更好的解决方案可能是明智之举;
尤其是当 SELinux 提供大量配置选项来允许给定服务权限执行仅有的你预计它要做的就是这些,仅此而已!然而,由于控制选项数量庞大,管理员必须了解存在哪些选项,并决定如何/何时/在何处有效地实施它们。正如我所提到的,首先要查看的是系统的手册页以及 中的审计日志/var/log/audit/audit.log
。例如,要在日志文件中搜索有关 avahi 的消息,请执行:
# grep /usr/sbin/avahi /var/log/audit/audit.log
编辑:反映更新的问题
msg=avc: denied { send_msg } for msgtype=method_return dest=:1.114
spid=731 tpid=14478 scontext=system_u:system_r:avahi_t:s0
tcontext=system_u:system_r:init_t:s0
查看手册页
以下事项尤其应该引起您的兴趣:
system_dbusd_t
SELinux 类型:$ man system_dbusd_selinux
avahi_t
SELinux 类型:$ man avahi_selinux
- 看看
avahi_exec_t
avahi_initrc_exec_t
文件上下文avahi_var_run_t
avahi_unit_file_t
- 以及相关清单布尔值其中。
- 看看
好吧,由于我不确定您是否注意到了最后一点avahi_exec_t
;并且由于我还不能发表评论 :/;以下是来自手册页本身的相关信息:
SELinux 为 avahi 定义了文件上下文类型,如果您想要将这些类型的文件存储在不同的路径中,则需要执行 semanage 命令来指定备用标签,然后使用 restorecon 将标签放到磁盘上。
semanage fcontext -a -t avahi_exec_t '/srv/avahi/content(/.*)?' restorecon -R -v /srv/myavahi_content Note: SELinux often uses regular expressions to specify labels that match multiple files. The following file types are defined for avahi: avahi_exec_t - Set files with the avahi_exec_t type, if you want to transition an executable to the avahi_t domain. Paths: /usr/sbin/avahi-daemon, /usr/sbin/avahi-autoipd, /usr/sbin/avahi-dnsconfd avahi_initrc_exec_t - Set files with the avahi_initrc_exec_t type, if you want to transition an executable to the avahi_initrc_t domain. avahi_unit_file_t - Set files with the avahi_unit_file_t type, if you want to treat the files as avahi unit content.
SELinux 和进程转换
前往Dan Walsh 的博客有关 SELinux 的一些详细讨论/信息,这篇文章特别提到
进程转换表示当以标签 a_t 运行的进程执行标签为 b_exec_t 的文件时,它应该以 b_t 的形式执行进程。例如,服务 httpd start。在本例中,我们让 unconfined_t 运行标签为 initrc_exec_t 的 init 脚本,SELinux 以 initrc_t 的形式启动进程。
除此之外,你最好继续研究该tvheadend
程序以及 SELinux 管理。你可以创建一个自定义策略根据audit
日志消息的建议;例如:
# grep tvheadend /var/log/audit/audit.log | audit2allow -M mypol
# semodule -i mypol.pp
至少直到出现更好的解决方案,和/或tvheadend
进入 Fedora 存储库。最后,仔细查看您为创建的单元文件(服务文件)systemd
;检查是否存在错误、潜在的添加和更改。
答案3
你可以使用以下方法修复此问题audit2allow创建自定义策略模块
audit2allow -M custom_avhi <file_containing_AVC-denied messages
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i custom_avhi.pp