O systemd não protege processos contra a aquisição de um terminal de controle?

1

man 7 daemon

When a traditional SysV daemon starts, it should execute the following steps as part of the initialization. Note that these steps are unnecessary for new-style daemons (see below), and should only be implemented if compatibility with SysV is essential.

[...]

6. In the child, call setsid() to detach from any terminal and create an independent session.

7. In the child, call fork() again, to ensure that the daemon can never re-acquire a terminal again.

mas compare isso aos processos iniciados sem nenhum vestígio de compatibilidade com o SysV:

$ ps -efj
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root         1     0     1     1  0 May10 ?        00:06:44 /sbin/init
...
root       185     1   185   185  0 May10 ?        00:09:48 /lib/systemd/systemd-journald
root     16434     1 16434 16434  0 May26 ?        00:00:11 /usr/sbin/rsyslogd -n

Os processos para rsyslog.service e systemd-journal.service são líderes de sessão (SID = PID).

Parece que se tais programas fossem configurados para logar em um TTY, eles ganhariam o TTY como um terminal de controle e receberiam um sinal indesejado / fatal quando o TTY fosse desligado / recebesse Ctrl + C, respectivamente. A menos que eles se lembrem de definir O_NOCTTY ao abrir o arquivo TTY.

Parece que é um pouco difícil escrever ou converter um programa para ser executado como um serviço systemd sem qualquer compatibilidade com o SysV, se o seu programa suportar a gravação de mensagens em arquivos personalizados. Não parece ser apontado por este documento que defende o estilo do sistema. O doc implica no contrário, insistindo que o double-fork é necessário para evitar isso no SysV e, em seguida, não mencionando isso como um problema ao descrever as etapas que um serviço systemd nativo usaria.

Isso está correto? O systemd fornece alguma proteção contra isso que eu negligenciei ou a questão é apontada em outro lugar no systemd doc?

    
por sourcejedi 01.06.2018 / 10:59

2 respostas

1

O systemd não protege programas de serviço contra a aquisição de um terminal de controle. Eles precisam se proteger ao abrir arquivos de log especificados pelo usuário, usando o sinalizador O_NOCTTY .

$ rpm -q systemd
systemd-238-8.git0e0aa59.fc28.x86_64

$ systemctl cat test
# /etc/systemd/system/test.service
[Service]
Type=simple
ExecStart=/bin/sh -c "exec cat </dev/tty10 >/dev/tty10"

$ systemctl status test
● test.service
   Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
   Active: active (running) since Fri 2018-06-01 11:28:41 BST; 1min 35s ago
 Main PID: 12173 (cat)
    Tasks: 1 (limit: 4915)
   Memory: 180.0K
   CGroup: /system.slice/test.service
           └─12173 cat

Jun 01 11:28:41 alan-laptop systemd[1]: Started test.service.

$ ps -ejf
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
...
root     12173     1 12173 12173  0 11:28 tty10    00:00:00 cat

Eu também confirmei que mudar para tty10 e pressionar Ctrl + C para o processo cat .

    
por 01.06.2018 / 12:36
2

Does systemd provide some protection against this […]?

Você está assumindo que deveria. Pelo contrário, considere configurações como TTYPath e serviços como [email protected] . A capacidade de obter um terminal de controle é realmente necessária , para que o gerenciamento de serviços possa abranger os serviços de login do TTY, que precisam fazer exatamente isso.

O que realmente protege contra isso é o afastamento da alocação automática de um terminal de controle em open() e o descarte da semântica antiga. Ou iria proteger contra isso. Não é o caso do Linux, mas no FreeBSD, NetBSD, OpenBSD e Hurd, atualmente o O_NOCTTY flag to open() é totalmente supérfluo. A maneira somente de adquirir um terminal de controle é explicitamente exigida, com ioctl(…TIOSCTTY) . Este tem sido o caso de se aproximar de um quarto de século, desde os dias de 4.4BSD.

Nesse meio tempo, o hábito de entrar no Linux é o hábito que também tem sido o caso há muito tempo, muito antes do systemd: O_NOCTTY em todos os lugares . ☺

(Sim, as bibliotecas GNU e musl C não dão isso a você por fopen() . Esse é um dos vários motivos pelos quais fdopen() ainda é um mecanismo útil.)

O gerenciamento de serviços com service-manager do conjunto de ferramentas do nosh tem uma abordagem um pouco diferente disso. Em vez de sempre transformar os processos de daemon em líderes de sessão, cada serviço recebe seu próprio objeto de sessão do kernel que não vê uso, somente serviços específicos também encadeiam através de setsid explicitamente; como ttylogin@* services que usam open-controlling-tty , agetty@* services, onde é claro que agetty está configurando o terminal de controle e getty@* services. (Como observado na fonte de serviço, mgetty chama setsid() .)

Leitura adicional

por 01.06.2018 / 15:11

Tags