如何configurationSELinux以允许特定服务与Avahi进行通信?

我有一个运行在Fedora 20机器上的服务,当它开始尝试向Avahi注册服务时。 如果我的服务是在SELinux处于宽容模式时启动的,但是在SELinux强制执行时服务将不会注册。

我知道SELinux中的httpd_dbus_avahi布尔值。 这完美地允许Apache注册服务,但是我一直无法find关于如何允许其他特定服务与Avahi进行通信的许多信息。

更具体地说,我试图允许tvheadend向Avahi注册其HTSP服务,但我也很好奇如何允许任何特定的服务与Avahi进行通信,而不被SELinux阻止。 我不想closuresSELinux,也不想让进程与Avahi沟通。


编辑:添加所有SELinux和有关tvheadend的服务单位信息

— SELinux的—

audit.log消息

在执行semodule -DB并重新启动tvheadend服务之后。 以下是审计日志中显示的所有消息。 最后的消息似乎是问题,但我不知道该怎么做…

 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输出 ps -AZ | grep tvheadend

 system_u:system_r:init_t:s0 2599 ? 00:00:06 tvheadend 

我注意到init_t进程types似乎有点奇怪,因为我系统上的所有其他服务都具有initrc_t进程types。 我不知道为什么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文件可能会变得相当大,因此此用户在远大于系统分区的单独分区上有主目录。

当我创build这个用户时,我没有使用带useradd命令的--system开关。 也许我应该有?

可执行文件

ls -Z /usr/local/bin | grep tvheadend 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 

作为init_t运行这个服务可能不是一个好主意。

你得到这种行为的原因是因为tvheadend 可能被标记为bin_t ,并且不存在将这种types的文件移出init_t上下文的转换规则。

你可以search这个来确定..

 $ sesearch -s init_t --type -c process | grep bin_t 

该命令不返回结果。 bin_t进程没有从init_t转换出来。

你也应该避免在initrc_t运行这个types,因为它不适合服务。 事实上, 最好的解决办法是正确地为你服务,写一个有限的政策,但是这不在这个答案的范围之内。

相反,你需要将你的进程从init_t到另一个types。 因为这个应用程序不存在任何策略,所以最好把它移到unconfined_t ,为此types转换确实存在。

 $ 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不会被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 -ff /usr/bin/tvheadend 

然后恢复。

 restorecon /usr/bin/tvheadend 

现在,重新运行您的服务应该工作。 如果你重新运行ps -AZ | grep tvheadend ps -AZ | grep tvheadend你应该看到你的进程在unconfined_t中运行。

理想情况下,该scheme应该采用新政策,但是如果没有政策存在,最好在unconfined_t域中完全没有政策地运行。 initrc_tinit_t并不是真的用来运行服务(尽pipe有些不正确地进入服务), initrc_t最初被设想为运行init_t shell脚本,而init_t则用于运行systemd / init本身。

apache_selinux的手册页提到# semanage permissive可以用来允许特定的进程在宽容模式下运行。

 # semanage permissive -a avahi_t 

我build议find一些关于它的用法的更详细的信息

尽pipefind一个比“允许服务许可”访问控制更好的解决scheme可能是明智的做法,

特别是当SELinux提供了大量的configuration选项来允许给定的服务权限只做期望的事情时,更不用说了! 然而,由于这种广泛的控制选项,pipe理员必须了解存在哪些选项,并决定如何/何时/何地有效实施它们。 正如我所提到的,首先要查看的是系统中的联机帮助页面,以及/var/log/audit/audit.log的审计日志。 要search有关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 

看看Manpages

以下项目特别值得您关注:

  • system_dbusd_t SELinuxtypes:

     $ man system_dbusd_selinux 
  • avahi_t SELinuxtypes:

     $ man avahi_selinux 
    • 看看avahi_exec_t
    • avahi_initrc_exec_t文件上下文
    • avahi_var_run_t
    • avahi_unit_file_t
    • 以及其中相关的布尔值列表。

好的,因为我不确定你是否注意到avahi_exec_t上的最后一位; 因为我不能发表评论:/然而; 以下是联机帮助页的相关信息:

SELinux定义了avahi的文件上下文types,如果你想以不同的path存储这些types的文件,你需要执行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的一些详细的讨论/信息,特别提到这个post

一个进程转换表明,当进程作为标签运行时,a_t执行一个标记为b_exec_t的文件,它应该执行进程为b_t。这个例子是service httpd start。 在这种情况下,我们有unconfined_t运行一个标签为initrc_exec_t的初始化脚本,SELinux作为initrc_t启动该进程。

除此之外,你最好的select是继续研究tvheadend程序,以及SELinuxpipe理。 您可以按照audit日志消息的build议创build自定义策略 ; 就像是:

 # grep tvheadend /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp 

至less在更好的解决scheme出现之前,和/或tvheadend才能进入Fedora回购站。 最后,请仔细看看为systemd创build的单元文件(服务文件) 检查错误,潜在的增加和变化。

您可以使用audit2allow来修复此问题以创build自定义策略模块

 audit2allow -M custom_avhi <file_containing_AVC-denied messages ******************** IMPORTANT *********************** To make this policy package active, execute: semodule -i custom_avhi.pp