
Para o pull request do Metasploit
Isso pode resolver a issue #8571, que solicita módulos Phoenix Talon.
Na máquina alvo, um double-free é desencadeado devido ao kernel manter uma cópia extra de mc_list no momento do accept().
Uma máquina executando um kernel 4.10.15 ou inferior está em risco se estiver executando a seguinte rotina:
sockfd = socket(AF_INET, xx, IPPROTO_TCP);
setsockopt(sockfd, SOL_IP, MCAST_JOIN_GROUP, xxxx, xxxx);
bind(sockfd, xxxx, xxxx);
listen(sockfd, xxxx);
newsockfd = accept(sockfd, xxxx, xxxx);
close(newsockfd); // trigger release calls, handoff to RCU
sleep(5); // wait for rcu to free()
close(sockfd); // second free()
O socket pai, sockfd, é criado. É adicionado ao grupo multicast com a opção MCAST_JOIN_GROUP.
Ao adicionar o socket ao grupo multicast na interface local, o kernel aloca memória. Neste ponto,
mc_list existe no socket pai.
Depois que um endereço é atribuído ao socket com bind(), listen() para a conexão e accept().
accept() cria um novo socket, newsockfd, para o qual todos os campos necessários do pai são copiados,
incluindo o valor do ponteiro mc_list. Neste ponto, existem múltiplos ponteiros apontando
para o mesmo bloco de memória, daí o double free.
Quando a conexão é estabelecida, o kernel cria um socket filho que herda o objeto mc_list do socket pai.
Esta falha de herança está em inet_csk_clone_lock na linha 648 do arquivo net/ipv4/inet_connection_sock.c.
Veja o patch para ver a correção de uma linha para esta herança não intencional.
Em seguida, feche o socket filho. Como explicado acima, isso não libera o objeto mc_list.
Ele passa pela estrutura RCU (remote-copy-update) para liberar memória.
sleep() por alguns segundos para garantir que a passagem do RCU tenha tempo suficiente para chamar kfree().
Finalmente, feche o socket pai, o que irá desencadear o segundo free.
DoS simples. Dispara remotamente um double-free em uma máquina alvo conhecida executando a rotina de servidor necessária (explicada acima). Isso causa um kernel panic.