Dup de processo cruzado no Linux

Dup de processo cruzado no Linux

Gostaria de duplicar um descritor de arquivo em execução em um processo não relacionado no Linux. Eu sei sobreenviar mensagem(2)e SCM_RIGHTS(por exemplohttps://stackoverflow.com/questions/4489433/sending-file-descriptor-over-unix-domain-socket-and-select) , mas isso só funciona se o outro processo estiver cooperando. Preciso de uma solução que não necessite da cooperação ativa do outro processo. Também sei que poderia criar primeiro o descritor de arquivo, manter uma cópia e depois criar o outro processo, mas preciso de uma solução em que o outro processo crie seu próprio descritor de arquivo.

Posso ver o descritor de arquivo:

$ ls -l /proc/13115/fd/3
lrwx------ 1 pts pts 64 2013-05-04 13:15 /proc/13115/fd/3 -> socket:[19445454]

Porém, open("/proc/13115/fd/3", O_RDWR)executado em outro processo retorna o erroNenhum dispositivo ou endereço. Existe algo mais que funcionaria? Provavelmente comrastreamento?

Responder1

Isso ocorre intencionalmente: o compartilhamento de descritores de arquivos com outros processos é explícito. Por padrão, os descritores de arquivo são tão privados quanto a memória do próprio processo.

Como de costume, se você tiver o direito derastreamentoo processo, você pode fazer o que quiser, inclusive chamá-lo sendmsg. Tradicionalmente, a chamada ptraceexige a execução com o mesmo ID de usuário; restrições de segurança como SELinux, capacidades, prisões e assim por diante podem tornar ptracemais restritivas. Por exemplo, na configuração padrão do Ubuntu, um processo não-root só pode chamar ptraceseus próprios descendentes (por meio do AppArmor).

Usar ptracede forma robusta é um pouco complicado: você precisa injetar os dados corretos, certificar-se de não sobrescrever nada e limpar tudo sozinho. Portanto, minha recomendação é injetar o código de forma indireta e acionar esse código com uma ferramenta existente.

Escreva uma pequena biblioteca compartilhada contendo o sendmsgcódigo e LD_PRELOADenvie-o para o outro processo. Aqui estão algunsnão testadocódigo esqueleto com verificação de erros ausente.

int pts_gift_fd (char *path, int fd) {
    int sock;
    struct sockaddr_un addr = {0};
    struct msghdr msg = {0};
    struct iovec iov = {0};
    addr.sun_family = AF_UNIX;
    strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
    /* Populate msg, iov as in the code you've already found */
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    sendmsg(sock, &msg, 0);
    close(sock);
}

Então, para acionar o código, execute gdb -n -pid 13115 -batch -x /dev/stdine popenalimente-o com uma entrada como esta (onde %destá o fd que você deseja obter e %sé um caminho para um soquete unix que você criou anteriormente e está ouvindo):

call pts_gift_fd("%s", %d)
detach
quit

Responder2

Você não pode fazer isso pela mesma razão que não pode acessar a memória de um processo não relacionado, porque um descritor de arquivoéparte da memória de outro processo. A única razão pela qual há informações sobre coisas como esta /procé porque o kernel as fornece lá, e é somente leitura (portanto, existem meios de examinaruma cópiade memória de processo).

Se estiver relacionado a um arquivo, você pode tentar acessar o arquivo. Se for um soquete, você pode bisbilhotar usandolibpcapou algo derivado dele.

A situação é basicamente esta: um descritor de arquivo faz (novamente) parte da memória de um processo. O descritor possui um buffer subjacente que existe no espaço do kernel; quando o processo lê ou grava de/para o descritor, ele está gravando de e para esse buffer. Para saída de dados, o kernel libera o buffer (para o hardware) apropriadamente; para os dados que chegam, ele recarrega o buffer (do hardware) quando o processo o esvazia. Esses buffers não são, AFAIK, acessíveis a outros processos, embora existam alguns meios (por exemplo, libpcap) deleituraos dados de alguma forma determinada pela interface do kernel específica, assim como a interface proc pode fornecer alguns dados da memória do espaço do usuário do processo.

informação relacionada