CVE-2023-20938
English
Análise de Vulnerabilidade
- O cliente A e o cliente B estabelecem uma conexão Binder através do gerenciador de contexto servicemanager
- A cria o node 0xbeef (node = binder_new_node(proc, fp);), B referencia o node 0xbeef através de ref->target_node
- B primeiro processa corretamente o target_node 0xbeef, armazena a transação binder_transaction que referencia o target_node 0xbeef na fila de transações de A (binder_enqueue_work_ilocked(&t->work, &proc->todo);), permitindo que A possa referenciar novamente um ponteiro pendente já liberado
- B usa um offsets_size não alinhado para entrar no código de tratamento de erro (IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))), fazendo com que um buffer_offset ainda zero seja passado para a função binder_transaction_buffer_release, desencadeando a vulnerabilidade
- A função binder_transaction_buffer_release chama binder_dec_node_nilocked através de binder_dec_node, decrementa o contador de referência local_strong_refs do node 0xbeef, mas a instância do node possui múltiplos contadores de referência e listas de referência, e a liberação só é acionada quando todos esses contadores são zerados
- Fechar o binder de B aciona binder_cleanup_ref_olocked, neste momento também chama binder_dec_node_nilocked. Quando binder_dec_node_nilocked retorna true, o ponteiro ref->node que aponta para node(0xbeef) não será limpo
- Em seguida, será chamado binder_free_ref, na função binder_free_ref o node 0xbeef será liberado
- A irá referenciar novamente o node 0xbeef já liberado dentro da função binder_thread_read
Nota adicional: No ambiente Android real, aplicativos comuns não podem registrar serviços através do servicemanager, mas podem implementar a conexão entre dois processos através do ITokenManager. Este caso de teste usa o ITokenManager.