Como configurar o SELinux para permitir que serviços específicos se comuniquem com o Avahi?

4

Eu tenho um serviço, rodando em uma máquina Fedora 20, que quando iniciado tenta registrar serviços com o Avahi. Isso funciona perfeitamente se o meu serviço for iniciado enquanto o SELinux estiver no modo permissivo, mas o serviço não será registrado quando o SELinux for aplicado.

Estou ciente do httpd_dbus_avahi booleano no SELinux. Isso funciona perfeitamente para permitir que o Apache registre serviços, mas não consegui encontrar muita informação sobre como permitir que outros serviços específicos se comuniquem com o Avahi.

Mais especificamente, estou tentando permitir que o tvheadend registre seu serviço HTSP com o Avahi, mas também estou curioso para saber como um serviço específico pode se comunicar com o Avahi sem ser interrompido pelo SELinux. Eu não estou interessado em desligar o SELinux ou tornar o processo permissivo que deseja se comunicar com o Avahi.

EDIT: adicionou todas as informações do SELinux e da unidade de serviço relacionadas ao tvheadend

--- SELinux ---

audit.log messages

Depois de executar semodule -DB e reiniciar o serviço tvheadend. A seguir estão todas as mensagens que apareceram no log de auditoria. A última mensagem parece ser o problema, mas não tenho certeza do que fazer com isso ...

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=?'

Processo

Saída de ps -AZ | grep tvheadend

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

Percebi que o tipo de processo init_t parece um pouco estranho, pois todos os outros serviços no meu sistema têm o tipo de processo initrc_t . Eu não tenho certeza porque o serviço de tvheadend é diferente desta maneira.

Utilizador

Saída de 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

Eu uso este usuário apenas para executar o serviço tvheadend. Este usuário tem um diretório inicial em uma partição separada muito maior que a partição do sistema, já que os arquivos DVR gerados pelo tvheadend podem se tornar muito grandes.

Quando criei este usuário, não usei a opção --system com o comando useradd . Talvez eu deveria ter?

Executável

Saída de ls -Z /usr/local/bin | grep tvheadend

-rwxr-xr-x. root root system_u:object_r:bin_t:s0       tvheadend

--- Serviço ---

Arquivo de unidade

[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

Arquivo de ambiente da unidade

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
    
por Louis Daprato 23.02.2014 / 17:17

3 respostas

6

A execução deste serviço como init_t provavelmente não é uma ótima ideia.

O motivo pelo qual você obtém esse comportamento é porque tvheadend é provavelmente rotulado bin_t e não existe nenhuma regra de transição para remover um arquivo desse tipo do contexto init_t .

Você pode pesquisar isso para saber com certeza.

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

Este comando não retorna nenhum resultado. Nenhuma transição de init_t para um processo bin_t .

Você também deve evitar a execução desse tipo em initrc_t , já que não é apropriado para o serviço. De um modo geral, a melhor solução seria escrever uma política confinada para o seu serviço, mas isso está além do escopo desta resposta.

Em vez disso, você precisa tirar seu processo de init_t de outro tipo. Como não existe política para este aplicativo, provavelmente é melhor movê-lo para unconfined_t , para o qual existe uma transição de tipo.

$ 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;

Também podemos verificar se a regra que está sendo atingida na política não será atingida em unconfined_t (o que não deveria).

$ 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 ;

Para isso, basta reclassificar seu programa tvheadend para unconfined_exec_t .

semanage fcontext -a -t unconfined_exec_t -f f /usr/bin/tvheadend

Em seguida, restaure.

restorecon /usr/bin/tvheadend

Agora, volte a executar o seu serviço deve funcionar. Se você executar novamente o ps -AZ | grep tvheadend , verá o processo em execução em unconfined_t .

Idealmente, uma nova diretiva deve ser usada para este programa, mas se nenhuma diretiva existir, é melhor executá-la sem diretivas no domínio unconfined_t . initrc_t e init_t não são realmente usados para rodar serviços (embora alguns executem incorretamente), initrc_t foi originalmente concebido para rodar scripts de shell SYSV e init_t é para rodar o próprio systemd / init .

    
por 27.02.2014 / 20:19
3

A página manpage para apache_selinux menciona que # semanage permissive pode ser usado para permitir que processos específicos sejam executados no modo permissivo .

# semanage permissive -a avahi_t

Sugiro que você encontre informações mais detalhadas sobre seu uso

No entanto, pode ser sensato encontrar uma solução melhor do que simplesmente "permitir um serviço permissivo" aos controles de acesso;

especialmente quando o SELinux fornece um grande número de opções de configuração para permitir que determinadas permissões de serviço façam apenas as coisas que você espera , e nada mais!  Devido a esse vasto número de opções de controle, no entanto, os administradores precisam aprender quais opções existem e decidir como / quando / onde implementá-las de maneira eficaz. Como mencionei, o primeiro lugar a procurar está nas páginas do seu sistema, bem como no seu log de auditoria em /var/log/audit/audit.log . Para procurar mensagens sobre o avahi, por exemplo, dentro de seus arquivos de log, execute:

# grep /usr/sbin/avahi /var/log/audit/audit.log

EDITAR: para refletir a pergunta atualizada

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

Dê uma olhada nas Manpages

Os itens a seguir, em particular, devem ser de seu interesse:

  • system_dbusd_t Tipo de SELinux:

    $ man system_dbusd_selinux
    
  • avahi_t Tipo de SELinux:

    $ man avahi_selinux
    
    • dê uma olhada no avahi_exec_t
    • avahi_initrc_exec_t contextos de arquivos
    • avahi_var_run_t
    • avahi_unit_file_t
    • bem como a lista de booleans relacionados aqui

Tudo bem, já que não tenho certeza se você percebeu esse último bit em avahi_exec_t ; e como não posso postar comentários: / yet; aqui está a informação pertinente da página manpage:

SELinux defines the file context types for the avahi, if you wanted to store files with these types in a diffent paths, you need to execute the semanage command to sepecify alternate labeling and then use restorecon to put the labels on disk.

   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 e Transições de Processo

Vá ao blogue de Dan Walsh para uma discussão / informação detalhada sobre o SELinux, este post em particular menciona

A process transition says when process running as label a_t executes a file labeled b_exec_t it should execute the process as b_t An example of this would be service httpd start. In this case we have unconfined_t running an init script labeled initrc_exec_t and SELinux starts the process as initrc_t.

Além disso, sua melhor aposta é continuar pesquisando o programa tvheadend , assim como o gerenciamento do SELinux. Você pode criar uma política personalizada conforme sugerido pelas mensagens audit log; algo como:

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

Pelo menos até que surjam melhores soluções, e / ou tvheadend chegar ao fedora repos. Por fim, observe melhor o arquivo de unidade (arquivo de serviço) que você criou para systemd ; verificar erros, adições e alterações em potencial.

    
por 24.02.2014 / 11:09
1

Você pode corrigir isso usando audit2allow para criar um módulo de política personalizado

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

semodule -i custom_avhi.pp
    
por 27.02.2014 / 17:42