CVE-2023-20938
English
Analisi della vulnerabilità
- Il client A e il client B stabiliscono una connessione Binder tramite il context manager servicemanager
- A crea il node 0xbeef (node = binder_new_node(proc, fp);), B fa riferimento al node 0xbeef tramite ref->target_node
- B prima gestisce correttamente target_node 0xbeef e inserisce la transazione binder_transaction che fa riferimento a target_node 0xbeef nella coda delle transazioni di A (binder_enqueue_work_ilocked(&t->work, &proc->todo);), consentendo ad A di fare nuovamente riferimento al puntatore pendente liberato
- B utilizza un offsets_size non allineato per entrare nel codice di gestione degli errori (IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))), facendo sì che un buffer_offset ancora pari a 0 venga passato alla funzione binder_transaction_buffer_release, innescando così la vulnerabilità
- La funzione binder_transaction_buffer_release chiama la funzione binder_dec_node_nilocked tramite binder_dec_node, decrementando il contatore di riferimenti local_strong_refs del node 0xbeef; tuttavia, l'istanza del node dispone di più contatori di riferimenti ed elenchi di riferimenti e il rilascio viene innescato solo quando tutti questi contatori vengono azzerati
- La chiusura del binder di B attiva la funzione binder_cleanup_ref_olocked; in questo momento viene chiamata anche binder_dec_node_nilocked e, quando binder_dec_node_nilocked restituisce true, il puntatore ref->node che punta al node (0xbeef) non verrà azzerato
- Successivamente verrà chiamata binder_free_ref; nella funzione binder_free_ref il node 0xbeef viene liberato
- A farà nuovamente riferimento al node 0xbeef già liberato nella funzione binder_thread_read
Note aggiuntive:
In un ambiente Android reale, un'applicazione con permessi ordinari non può registrare servizi tramite servicemanager, ma può realizzare il collegamento dei due processi tramite ITokenManager; questo caso di test utilizza appunto ITokenManager