Por que o comprimento do caminho do soquete é limitado a cem caracteres?

18

Nos sistemas Unix, os nomes dos caminhos geralmente não têm praticamente nenhuma limitação de comprimento (bem, 4096 caracteres no Linux) ... exceto os caminhos dos arquivos de soquete, que são limitados a cerca de 100 caracteres (107 caracteres no Linux ).

  • Primeira pergunta: por que uma limitação tão baixa?

Verifiquei que parece possível contornar essa limitação alterando o diretório de trabalho atual e criando em vários diretórios vários arquivos de soquete, todos usando o mesmo caminho ./myfile.sock: os aplicativos clientes parecem se conectar corretamente aos processos esperados do servidor, embora lsofmostre tudo deles ouvindo no mesmo caminho do arquivo de soquete.

  • Esta solução alternativa é confiável ou tive apenas sorte?
  • Esse comportamento é específico do Linux ou esta solução alternativa também pode ser aplicada a outros Unixes?
WhiteWinterWolf
fonte
O limite é ainda mais baixo (104) nos sistemas atuais do OpenBSD ou no Mac OS X 10.11.
thrig
O importante, é que ele tem que ser menor do que 108, por uma questão de compatibilidade :)
AFAIK são 108 caracteres no Linux. Por favor, verifique /usr/include/$arch-linux-gnu/sys/un.h na sua máquina.
Schaiba # 25/17
@schaiba: 108 bytes, o que significa uma sequência de 107 caracteres finalizada por um terminador nulo.
WhiteWinterWolf

Respostas:

18

Compatibilidade com outras plataformas ou compatibilidade com coisas mais antigas para evitar excedentes ao usar snprintf()e strncpy().

Michael Kerrisk explica em seu livro na página 1165 - Capítulo 57, Sockets: Domínio Unix:

O SUSv3 não especifica o tamanho do campo sun_path. As primeiras implementações do BSD usavam 108 e 104 bytes, e uma implementação contemporânea (HP-UX 11) usa 92 bytes. Os aplicativos portáteis devem codificar para esse valor mais baixo e usar snprintf () ou strncpy () para evitar excedentes de buffer ao gravar neste campo.

Os caras do Docker até tiraram sarro disso, porque alguns soquetes tinham 110 caracteres:

É por isso que o LINUX usa um soquete de 108 caracteres. Isso pode ser alterado? Claro. E é por isso que, em primeiro lugar, essa limitação foi criada em sistemas operacionais mais antigos:

Citando a resposta:

Era para combinar com o espaço disponível em uma estrutura de dados do kernel acessível.

Citando "O Projeto e Implementação do Sistema Operacional 4.4BSD" por McKusick et. al. (página 369):

Os recursos de gerenciamento de memória giram em torno de uma estrutura de dados chamada mbuf. Mbufs, ou buffers de memória, têm 128 bytes de comprimento, com 100 ou 108 bytes desse espaço reservado para armazenamento de dados.

Outros SOs (soquetes de domínio unix):


fonte
11
O SUSv3 XNET ficou em silêncio porque não havia consenso sobre o assunto.
Fpmurphy 24/05
Você tem algum link para provar seu ponto de vista?
Obrigado por esta resposta. É confiável usar vários arquivos de soquete com nomes idênticos em relação a diferentes diretórios de trabalho (por exemplo, criar um arquivo de soquetes nomeado ./my.socketabaixo do diretório A/e outro arquivo de soquete também nomeado ./my.socketabaixo do diretório B/)? lsofnão faz nenhuma distinção entre os dois arquivos de soquete, no entanto, ainda parece funcionar, mas eu me pergunto se isso é apenas porque tenho sorte. Essa seria uma boa solução alternativa para criar arquivos de soquete abaixo de um caminho que já é maior que o tamanho permitido.
WhiteWinterWolf
Buscando sockets Unix no meu servidor de correio, parece trazer nome completo do caminho: lsof -U| grep amavis(nova linha)amavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock
Sim, eu sei que isso é incomum, daí a minha pergunta aqui;)! Pelo que testei, nomes relativos funcionam, mas ainda me parece estranho ... mas funciona. Meu aplicativo não é de todo o sistema; portanto, os arquivos de soquete são armazenados com todos os outros dados do aplicativo em um local controlado pelo usuário, o que é altamente preferido, mas com um caminho potencialmente muito longo, ou posso ficar /tmprepleto de toneladas de diretórios não excluídos com nomes exclusivos cada contendo um único arquivo de soquete (totalmente feio, mas portátil e seguro).
WhiteWinterWolf
5

Quanto ao porquê, o nwildner já escreveu uma excelente resposta .

Aqui, focarei apenas em como e no uso do caminho relativo.

Internamente, enquanto o arquivo de soquete também pode ser procurado por nome (eu acho), eles geralmente são procurados por inode. No Linux, essa pesquisa é garantida pela função unix_find_socket_byinode()definida em net / unix / af_unix.c .

Isso pode ser facilmente verificado da seguinte forma:

  • Crie dois diretórios A / e B / .
  • Em cada diretório, faça um processo escutar nos arquivos de soquete com o mesmo nome. Com socatvocê usaria um comando como:
$ socat UNIX-LISTEN:./my.sock -
  • Agora troque os arquivos de soquete movendo A / my.sock para B / e vice-versa.
  • A partir de agora, se o aplicativo cliente se conectar ao A / my.sock, ele entrará em contato com o servidor B e, se ele se conectar ao B / my.sock , entrará em contato com o servidor A (observe que, quando a comunicação terminar, o processo do servidor poderá legitimamente exclua o que considera ser seu próprio arquivo de soquete).

Eu verifiquei esse comportamento em vários sistemas Unix (Linux Debian, FreeBSD e OpenIndiana para obter alguma diversidade), então esse comportamento parece ser pelo menos amplo, se não padrão.

Os caminhos absolutos geralmente são usados ​​como uma convenção entre os processos do cliente e do servidor, pois o processo do cliente pode não saber como estabelecer a comunicação inicial com o servidor.

No entanto, se essa comunicação inicial não for um problema, parece seguro usar caminhos relativos para a criação de arquivos de soquete, permitindo evitar problemas de comprimento de caminho quando o local do arquivo de soquete não for diretamente controlado pelo processo do servidor.

WhiteWinterWolf
fonte