CVE-2023-20938
English
脆弱性解析
- クライアントAとクライアントBは、コンテキストマネージャーservicemanagerを介してBinder接続を確立する
- Aがノード0xbeefを作成(node = binder_new_node(proc, fp);)、Bはref->target_nodeを介してnode 0xbeefを参照する
- Bがまずtarget_node 0xbeefを正しく処理し、target_node 0xbeefを参照するトランザクションbinder_transactionをAのトランザクションキューに格納する(binder_enqueue_work_ilocked(&t->work, &proc->todo);)。これによりAが解放済みのダングリングポインタを再び参照できるようになる
- Bがアライメントされていないoffsets_sizeを使用してエラー処理コードに入る(IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t)))。その結果、まだ0のbuffer_offsetがbinder_transaction_buffer_release関数に渡され、脆弱性が発動する
- binder_transaction_buffer_release関数はbinder_dec_nodeを介してbinder_dec_node_nilocked関数を呼び出し、ノード0xbeefのlocal_strong_refs参照カウンタを減少させる。しかし、ノードインスタンスには複数の参照カウンタと参照リストがあり、これらのカウンタがすべてゼロになった場合にのみ解放がトリガーされる
- Bのbinderを閉じるとbinder_cleanup_ref_olocked関数がトリガーされる。このとき再びbinder_dec_node_nilockedが呼び出され、binder_dec_node_nilockedがtrueを返すと、ノード(0xbeef)を指すポインタref->nodeがクリアされなくなる
- その後binder_free_refが呼び出され、binder_free_ref関数内でノード0xbeefが解放される
- Aはbinder_thread_read関数内で解放済みのnode 0xbeefを再び参照する
補足説明:
実際のAndroid環境では、通常のアプリ権限ではservicemanagerを介してサービスを登録できませんが、ITokenManagerを使用して2つのプロセス間のリンクを実現できます。本テストケースではITokenManagerを使用しています。