
Metasploit プルリクエスト用
これは、Phoenix Talonモジュールを要求する#8571の問題を解決する可能性があります。
ターゲットマシンでは、accept()時にカーネルがmc_listの余分なコピーを保持するため、ダブルフリーがトリガーされます。
以下のルーチンを実行している場合、カーネル4.10.15以下のマシンは危険にさらされます:
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); // 解放コールをトリガー、RCUにハンドオフ
sleep(5); // rcuがfree()するのを待つ
close(sockfd); // 2回目のfree()
親ソケットsockfdが作成されます。MCAST_JOIN_GROUPオプションでマルチキャストグループに追加されます。
ソケットをローカルインターフェースのマルチキャストグループに追加する際、カーネルはメモリを割り当てます。この時点で、
mc_listは親ソケットに存在します。
bind()でソケットにアドレスが割り当てられた後、接続のためにlisten()とaccept()を行います。
accept()は新しいソケットnewsockfdを作成し、親の必要なフィールドすべてがコピーされます。
これにはmc_listポインタの値も含まれます。この時点で、同じメモリブロックを指す複数のポインタが存在するため、ダブルフリーが発生します。
接続が確立されると、カーネルは親ソケットのmc_listオブジェクトを継承する子ソケットを作成します。
この継承の欠陥は、ファイルnet/ipv4/inet_connection_sock.cの648行目のinet_csk_clone_lockにあります。
パッチを参照して、この意図しない継承に対する一行の修正を確認してください。
次に、子ソケットを閉じます。上記の説明の通り、これではmc_listオブジェクトは解放されません。
メモリを解放するためにRCU(リモートコピー更新)構造を経由します。
sleep()で数秒待ち、RCUハンドオフがkfree()を呼び出すのに十分な時間を確保します。
最後に、親ソケットを閉じると、2回目の解放がトリガーされます。
単純なDoS。既知のターゲットマシンで、必要なサーバールーチン(上記で説明)を実行している場合に、リモートからダブルフリーをトリガーします。これによりカーネルパニックが発生します。