Isso ocorre por design: o compartilhamento de descritores de arquivos com outros processos é explícito. Por padrão, os descritores de arquivos são tão particulares quanto a própria memória do processo.
Como de costume, se você tem o direito de ptrace o processo, você pode fazer o que quiser, inclusive fazê-lo chame sendmsg
. Tradicionalmente, chamar ptrace
requer a execução como o mesmo ID do usuário; restrições de segurança, como SELinux, capacidades, cadeias, etc., podem tornar ptrace
mais restritivas. Por exemplo, na configuração padrão do Ubuntu, um processo não-raiz só pode chamar ptrace
em seus próprios descendentes (por meio do AppArmor).
Usar ptrace
de maneira robusta é um pouco complicado: você precisa injetar os dados corretos, certificar-se de não sobrescrever nada e limpar a si mesmo. Então, 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 código sendmsg
e LD_PRELOAD
para o outro processo. Veja alguns códigos esqueléticos não testados com a verificação de erros em falta.
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);
}
Em seguida, para acionar o código, execute gdb -n -pid 13115 -batch -x /dev/stdin
com popen
e insira-o dessa forma (onde %d
é o fd que você deseja obter e %s
é um caminho para um soquete unix que você vimos anteriormente e estamos ouvindo):
call pts_gift_fd("%s", %d)
detach
quit