CVE-2023-20938
English
Schwachstellenanalyse
- Client A und Client B stellen über den Kontextmanager servicemanager eine Binder-Verbindung her.
- A erstellt node 0xbeef (node = binder_new_node(proc, fp);), B referenziert node 0xbeef über ref->target_node (node 0xbeef)
- B verarbeitet zunächst target_node 0xbeef korrekt und speichert das binder_transaction-Objekt, das auf target_node 0xbeef verweist, in die Transaktionswarteschlange von A (binder_enqueue_work_ilocked(&t->work, &proc->todo);), sodass A erneut auf den freigegebenen hängenden Zeiger verweisen kann.
- B tritt aufgrund des nicht ausgerichteten offsets_size in den Fehlerbehandlungscode ein (IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))), was dazu führt, dass der noch 0 betragende buffer_offset an die Funktion binder_transaction_buffer_release übergeben wird, wodurch die Schwachstelle ausgelöst wird.
- Die Funktion binder_transaction_buffer_release ruft über binder_dec_node die Funktion binder_dec_node_nilocked auf, um den Referenzzähler local_strong_refs von node 0xbeef zu dekrementieren. Die node-Instanz enthält jedoch mehrere Referenzzähler und Referenzlisten; die Freigabe wird erst ausgelöst, wenn alle diese Zähler auf 0 gesetzt sind.
- Das Schließen des Binders von B löst die Funktion binder_cleanup_ref_olocked aus, wobei ebenfalls binder_dec_node_nilocked aufgerufen wird. Wenn binder_dec_node_nilocked true zurückgibt, wird der auf node (0xbeef) verweisende Zeiger ref->node nicht gelöscht.
- Anschließend wird binder_free_ref aufgerufen, und in der Funktion binder_free_ref wird node 0xbeef freigegeben.
- A wird in der Funktion binder_thread_read erneut auf den freigegebenen node 0xbeef verweisen.
Zusätzliche Anmerkungen:
In einer echten Android-Umgebung können normale Apps keine Dienste über servicemanager registrieren, aber sie können über ITokenManager eine Verbindung zwischen zwei Prozessen herstellen. Dieser Testfall verwendet ITokenManager.