CVE-2023-20938
English
Análisis de vulnerabilidad
- El cliente A y el cliente B establecen una conexión Binder a través del administrador de contexto servicemanager.
- A crea el nodo 0xbeef (node = binder_new_node(proc, fp);), B lo referencia mediante ref->target_node (nodo 0xbeef)
- B primero procesa correctamente target_node 0xbeef, almacenando la transacción binder_transaction que referencia a target_node 0xbeef en la cola de transacciones de A (binder_enqueue_work_ilocked(&t->work, &proc->todo);), permitiendo que A pueda volver a referenciar el puntero colgante liberado.
- B utiliza offsets_size no alineado para entrar en el código de manejo de errores (IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))), lo que provoca que buffer_offset, aún siendo 0, sea pasado a la función binder_transaction_buffer_release desencadenando así la vulnerabilidad.
- La función binder_transaction_buffer_release llama a la función binder_dec_node_nilocked a través de binder_dec_node, disminuyendo el contador de referencias local_strong_refs del nodo 0xbeef, pero la instancia del nodo tiene múltiples contadores de referencias y listas de referencias; solo se desencadena la liberación cuando todos estos contadores se ponen a cero.
- Cerrar el Binder de B desencadena la función binder_cleanup_ref_olocked, en este punto también se llama a binder_dec_node_nilocked; cuando binder_dec_node_nilocked devuelve true, no se limpiará el puntero ref->node que apunta al nodo (0xbeef).
- Posteriormente se llamará a binder_free_ref, en la función binder_free_ref se libera el nodo 0xbeef.
- A volverá a referenciar el nodo 0xbeef liberado en la función binder_thread_read.
Nota adicional:
En un entorno Android real, las aplicaciones comunes no tienen permiso para registrar servicios a través de servicemanager, pero pueden implementar la conexión entre dos procesos mediante ITokenManager. Este caso de prueba utiliza ITokenManager.