
Per Metasploit pull request
Questo potrebbe risolvere il problema #8571, che richiede moduli Phoenix Talon.
Sulla macchina target, viene attivato un double-free a causa del kernel che mantiene una copia extra di mc_list al momento di accept().
Una macchina che esegue un kernel 4.10.15 e precedenti è a rischio se esegue la seguente routine:
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()
Il socket padre, sockfd, viene creato. Viene aggiunto al gruppo multicast con l'opzione MCAST_JOIN_GROUP. Aggiungendo il socket al gruppo multicast sull'interfaccia locale, il kernel alloca memoria. A questo punto, mc_list esiste nel socket padre.
Dopo che un indirizzo viene assegnato al socket con bind(), listen() per la connessione e accept(). accept() crea un nuovo socket, newsockfd, a cui vengono copiati tutti i campi necessari del padre, incluso il valore del puntatore mc_list. A questo punto, ci sono più puntatori che puntano allo stesso blocco di memoria, da qui il double free.
Quando la connessione viene stabilita, il kernel crea un socket figlio che eredita l'oggetto mc_list del socket padre. Questo difetto di ereditarietà si trova in inet_csk_clone_lock alla riga 648 del file net/ipv4/inet_connection_sock.c. Vedi la patch per vedere la correzione di una riga per questa ereditarietà non intenzionale.
Successivamente, chiudi il socket figlio. Come spiegato sopra, questo non rilascia l'oggetto mc_list. Passa attraverso la struttura RCU (remote-copy-update) per rilasciare la memoria. sleep() per alcuni secondi per assicurarsi che il passaggio RCU abbia abbastanza tempo per chiamare kfree(). Infine, chiudi il socket padre, che attiverà il secondo free.
DoS semplice. Attiva da remoto un double-free su una macchina target nota che esegue la routine server richiesta (spiegata sopra). Questo causa un kernel panic.