Usar a Inicialização verificada

A inicialização verificada exige a verificação criptográfica de todo o código executável e dos dados que fazem parte da versão do Android que está sendo inicializada antes de ser usada. Isso inclui o kernel (carregado da partição boot), a árvore de dispositivos (carregada da partição dtbo), a partição system, a partição vendor e assim por diante.

Partições pequenas, como boot e dtbo, que são lidas apenas uma vez, geralmente são verificadas carregando todo o conteúdo na memória e calculando o hash. Esse valor de hash calculado é comparado ao valor de hash esperado. Se o valor não corresponder, o Android não será carregado. Para mais detalhes, consulte Fluxo de inicialização.

Partições maiores que não cabem na memória (como sistemas de arquivos) podem usar uma árvore de hash em que a verificação é um processo contínuo que acontece à medida que os dados são carregados na memória. Nesse caso, o hash raiz da árvore de hash é calculado durante o tempo de execução e é verificado em relação ao valor de hash raiz esperado. O Android inclui o driver dm-verity para verificar partições maiores. Se, em algum momento, o hash raiz calculado não corresponder ao valor de hash raiz esperado, os dados não serão usados e o Android vai entrar em um estado de erro. Para mais detalhes, consulte Corrupção de dm-verity.

Os hashes esperados geralmente são armazenados no final ou no início de cada partição verificada, em uma partição dedicada ou em ambos. É fundamental que esses hashes sejam assinados (direta ou indiretamente) pela raiz de confiança. Por exemplo, a implementação do AVB oferece suporte às duas abordagens. ConsulteInicialização verificada do Android para mais detalhes.

Proteção contra reversão

Mesmo com um processo de atualização totalmente seguro, é possível que um exploit de kernel do Android não persistente instale manualmente uma versão mais antiga e vulnerável do Android, reinicialize na versão vulnerável e use essa versão do Android para instalar um exploit persistente. A partir daí, o invasor tem a propriedade permanente do dispositivo e pode fazer qualquer coisa, incluindo desativar atualizações.

A proteção contra essa classe de ataques é chamada de proteção contra reversão. A proteção contra reversão geralmente é implementada usando armazenamento inviolável para registrar a versão mais recente do Android e se recusar a inicializar o Android se ele for mais antigo que a versão registrada. As versões geralmente são rastreadas por partição.

Para mais detalhes sobre como o AVB processa proteções contra reversão, consulte o README do AVB (link em inglês).

Processar erros de verificação

A verificação pode falhar no momento da inicialização (por exemplo, se o hash calculado na partição boot não corresponder ao hash esperado) ou no tempo de execução (por exemplo, se o dm-verity encontrar um erro de verificação na partição system). Se a verificação falhar no momento da inicialização, o dispositivo não poderá ser inicializado, e o usuário final precisará seguir as etapas para recuperar o dispositivo.

Se a verificação falhar no tempo de execução, o fluxo será um pouco mais complicado. Se o dispositivo usar o dm-verity, ele precisará ser configurado no modo restart. No modo restart, se um erro de verificação for encontrado, o dispositivo será reiniciado imediatamente com uma flag específica definida para indicar o motivo. O carregador de inicialização precisa notar essa flag e mudar o dm-verity para usar o modo de erro de E/S (eio) e permanecer nesse modo até que uma nova atualização seja instalada.

Ao inicializar no modo eio, o dispositivo mostra uma tela de erro informando ao usuário que foi detectada corrupção e que o dispositivo pode não funcionar corretamente. A tela é mostrada até que o usuário a dispense. No modo eio, o driver dm-verity não reinicia o dispositivo se um erro de verificação for encontrado. Em vez disso, um erro EIO é retornado, e o app precisa lidar com o erro.

A intenção é que o atualizador do sistema seja executado (para que um novo SO sem erros de corrupção possa ser instalado) ou que o usuário possa remover o máximo possível de dados do dispositivo. Depois que o novo SO for instalado, o carregador de inicialização vai notar o SO recém-instalado e voltar para o modo restart.