CVE-2023-20938
English
Analyse de la vulnérabilité
- Le client A et le client B établissent une connexion Binder via le gestionnaire de contexte servicemanager.
- A crée le nœud 0xbeef (node = binder_new_node(proc, fp);), B le référence via ref->target_node (node 0xbeef).
- B traite d'abord correctement target_node 0xbeef, en stockant la binder_transaction qui référence target_node 0xbeef dans la file d'attente des transactions de A (binder_enqueue_work_ilocked(&t->work, &proc->todo);), permettant à A de référencer à nouveau un pointeur pendant libéré.
- B utilise un offsets_size non aligné pour entrer dans le code de gestion d'erreur (IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))), ce qui fait que buffer_offset, encore à 0, est passé à la fonction binder_transaction_buffer_release, déclenchant ainsi la vulnérabilité.
- La fonction binder_transaction_buffer_release appelle binder_dec_node_nilocked via binder_dec_node, diminuant le compteur de références local_strong_refs du nœud 0xbeef. Mais l'instance du nœud possède plusieurs compteurs de références et listes de références ; la libération n'est déclenchée que lorsque tous ces compteurs sont mis à zéro.
- La fermeture du binder de B déclenche la fonction binder_cleanup_ref_olocked. À ce moment, binder_dec_node_nilocked est également appelée. Si binder_dec_node_nilocked renvoie true, le pointeur ref->node pointant vers le nœud (0xbeef) ne sera pas effacé.
- Ensuite, binder_free_ref est appelée, et dans binder_free_ref, le nœud 0xbeef est libéré.
- A va référencer à nouveau le nœud 0xbeef libéré dans la fonction binder_thread_read.
Remarque supplémentaire :
Dans un environnement Android réel, une application ordinaire ne peut pas enregistrer de services via servicemanager, mais elle peut utiliser ITokenManager pour établir un lien entre deux processus. Ce cas de test utilise ITokenManager.