Depois de ter aberto a parte master de um pseudoterminal
int fd_pseudo_term_master = open("/dev/ptmx",O_RDWR);
aí está o arquivo /dev/pts/[NUMBER]
criado, representando a slave
parte do pseudo-terminal.
Pessoas ignorantes, como eu, podem imaginar que, depois de ter feito ptsname(fd_pseudo_term_master,filename_pseudo_term_slave,buflen);
, deve-se simplesmente
fazer int fd_pseudo_term_slave = open(filename_pseudo_term_slave,O_RDWR);
e ser bom.
No entanto, deve haver um caso de uso muito importante de escravos pseudo-terminais "bloqueados", pois para simplificar as coisas, antes que a open
chamada possa ser feita, é necessário usar man 3 unlockpt , para "desbloqueá-lo".
Não consegui descobrir o que é esse caso de uso? Qual a necessidade do pseudo-terminal estar inicialmente bloqueado? O que é alcançado com o código (retirado de uma libc)
/* Unlock the slave pseudo terminal associated with the master pseudo
terminal specified by FD. */
int
unlockpt (int fd)
{
#ifdef TIOCSPTLCK
int save_errno = errno;
int unlock = 0;
if (ioctl (fd, TIOCSPTLCK, &unlock))
{
if (errno == EINVAL)
{
errno = save_errno;
return 0;
}
else
return -1;
}
#endif
/* If we have no TIOCSPTLCK ioctl, all slave pseudo terminals are
unlocked by default. */
return 0;
}
Se possível, uma resposta detalharia um caso de uso, histórico ou atual.
A parte bônus da pergunta seria:
Os kernels linux atuais ainda contam com essa funcionalidade de "escravos de pseudo terminal bloqueados?"
Ideia: Esta é uma tentativa ineficiente de evitar condições de corrida?
Esperando por uma resposta, examinei mais a fonte do kernel linux sem ter uma boa resposta. No entanto, parece que um uso que pode ser "extraído" de um caso de bloqueio inicial do pseudo-terminal é fornecer algum tempo para o processo mestre do pseudo-terminal configurar alguns direitos de acesso ao arquivo em /dev/pts/[NUMBER]
, para evitar que algum usuário para acessar o arquivo em primeiro lugar. Isso pode ser parte da resposta? Estranhamente, no entanto, parece que esse estado de "bloqueio inicial" não parece realmente capaz de impedir várias aberturas do arquivo escravo, pelo menos para o que concebo como atomicidade garantida aqui.
O antigo mecanismo AT&T System 5 para dispositivos escravos pseudoterminais era que eles eram nós de dispositivos de caracteres persistentes
/dev
comuns sob o . Havia um dispositivo mestre/dev/ptmx
multiplexador em . O antigo mecanismo 4.3BSD para dispositivos pseudoterminais tinha pares paralelos de nós de dispositivos mestre e escravo persistentes/dev
comuns sob .Em ambos os casos, isso significava que os arquivos do dispositivo escravo mantinham sua última propriedade e permissões após o fechamento do último descritor de arquivo. Daí a evolução da
grantpt()
função para fixar a propriedade e as permissões do arquivo do dispositivo escravo após a (re)alocação de um pseudoterminal (reutilizado).Isso, por sua vez, significava que havia uma janela quando um programa estava configurando um pseudoterminal reutilizado entre o
open()
e ograntpt()
onde quem possuía o dispositivo escravo anteriormente poderia entrar e abri-lo também, potencialmente obtendo acesso ao terminal de outra pessoa . Daí a ideia de dispositivos de caracteres escravos pseudoterminais iniciando em um estado bloqueado onde não poderiam ser abertos e sendo desbloqueadosunlockpt()
após agrantpt()
execução com sucesso.Ao longo dos anos, descobriu-se que isso era desnecessário.
Hoje em dia, os arquivos do dispositivo escravo não são persistentes, porque o kernel faz e destrói coisas em
/dev
si mesmo. O ato de abrir o dispositivo mestre redefine as permissões e a propriedade do dispositivo escravo ou cria o arquivo do dispositivo escravo novamente (no último caso, com o arquivo do dispositivo escravo desaparecendo novamente quando todos os descritores de arquivo abertos são fechados), em ambos os casos atomicamente em a mesma chamada de sistema.PTMGET
funcionalidade do controle de E/S no/dev/ptm
dispositivo./dev
ainda é um volume de disco, e o kernel emite internamente as chamadas relevantes para criar novos nós de dispositivo e redefinir suas propriedades e permissões.posix_openpt()
chamada do sistema./dev
não é um volume de disco. É um sistema dedevfs
arquivos. Ele não contém nenhum dispositivo "multiplexor" nem arquivos de dispositivo mestre, porqueposix_openpt()
é uma chamada de sistema direta, não umioctl()
descritor de arquivo aberto. Os dispositivos escravos aparecem no sistema dedevfs
arquivos em seupts/
diretório.O kernel, portanto, garante que eles tenham as permissões e propriedade corretas ab initio, e não há janela de oportunidade onde eles tenham as antigas. Assim, as funções da biblioteca
grantpt()
eunlockpt()
são essencialmente no-ops, cuja única funcionalidade restante é verificar seu descritor de arquivo passado e definirEINVAL
se não é o lado mestre de um pseudo-terminal, porque os programas podem estar fazendo coisas idiotas como passar não-pseudo -descritores de arquivo terminal para essas funções e esperando que eles retornem erros.Por um tempo no Linux, os dispositivos escravos pseudoterminais eram nós de dispositivos persistentes. A biblioteca GNU C
grantpt()
não era uma chamada de sistema. Em vez disso, ele bifurcou e executou um programa auxiliar set-UID chamadopt_chown
, para desgosto da multidão de executáveis sem set-UID . (grantpt()
tem que permitir que um usuário sem privilégios altere a propriedade e as permissões de um arquivo de dispositivo especial que ele não possui necessariamente, lembre-se.) Portanto, ainda havia a janela de oportunidade, e o Linux ainda precisava manter um bloqueio paraunlockpt()
.Seu "novo" sistema de
devpts
arquivos (onde "novo" significa introduzido há alguns anos atrás, agora) quase permite a mesma maneira de fazer as coisas como no FreeBSD comdevfs
, no entanto. Existem algumas diferenças.devpts
, este era umptmx
dispositivo em umdevtmpfs
sistema de arquivos diferente, com o sistema dedevpts
arquivos contendo apenas os arquivos de dispositivos escravos criados/destruídos automaticamente. Convencionalmente, a configuração era e uma montagem/dev/ptmx
acompanhante em .devpts
/dev/pts
devpts
arquivos, para contêineres e afins, e acabou sendo bastante difícil sincronizar os dois sistemas de arquivos (corretos) quando havia muitosdevtmpfs
sistemas dedevpts
arquivos. Portanto, no sistema "novo" mais recentedevpts
, todos os dispositivos, multiplexadores e escravos, estão em um sistema de arquivos. Para compatibilidade com versões anteriores, o padrão era que o novoptmx
nó fosse inacessível, a menos que fosse definido uma novaptmxmode
opção de montagem.devpts
optmx
arquivo de dispositivo no sistema dedevpts
arquivos agora é o multiplexador primário, e optmx
in thedevtmpfs
é um shim fornecido pelo kernel que tenta imitar um link simbólico, uma montagem de ligação ou um símbolo real simples e antigo ligar parapts/ptmx
.grantpt()
deveria. Definir as opções de montagem erradas, sejagid
diferente dotty
GID oumode
diferente de 0620, aciona o comportamento de fallback na biblioteca GNU C. Para reduzirgrantpt()
a uma não operação na biblioteca GNU C como desejado, o kernel não deve atribuir o grupo do processo de abertura (ou seja, deve haver umagid
configuração explícita), o grupo atribuído deve ser o grupotty
e omode
dispositivos escravos criados devem ser exatamente 0620.A não ativação
/dev/pts/ptmx
por padrão e a biblioteca GNU C não totalmente reduzidagrantpt()
a um no-op são ambos porque o kernel e a biblioteca C não são mantidos em sincronia. Cada um teve que operar com versões mais antigas do outro. O Linux ainda tinha que fornecer um arquivo/dev/ptmx
. A biblioteca GNU C ainda precisa voltar a funcionarpt_chown
se não houver um novodevpts
sistema de arquivos com as opções de montagem corretas.A janela de oportunidade, portanto, ainda existe para
unlockpt()
se proteger no Linux, se asdevpts
opções de montagem estiverem erradas e a biblioteca GNU C, consequentemente, tiver que voltar a fazer algo nograntpt()
.Leitura adicional
Documentation/filesystems/devpts.txt
. Núcleo Linux./dev/pts
deve usar o sinalizador de montagem 'newinstance' para evitar problemas de segurança com contêineres . Bug do Red Hat nº 501718.open-controlling-tty
. Guia de no . Programas.vc-get-tty
. Guia de no . Programas.pty-get-tty
. Guia de no . Programas.