A inicialização verificada exige a verificação criptográfica de todos os códigos executáveis e 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. Em seguida, 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 da raiz da árvore de hash é calculado durante o tempo de execução e verificado em relação ao valor esperado do hash da raiz. O Android inclui o driver dm-verity para verificar partições maiores. Se em algum momento o hash de raiz calculado não corresponder ao valor de hash de 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 do 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. É importante lembrar que esses hashes são assinados (direta ou indiretamente) pela raiz de confiança. Por exemplo, a implementação do AVB aceita as duas abordagens. Consulte Inicialização verificada do Android para mais detalhes.
Proteção contra reversão
Mesmo com um processo de atualização completamente seguro, é possível que um exploit não persistente do kernel do Android instale manualmente uma versão mais antiga e vulnerável do Android, reinicie na versão vulnerável e use essa versão do Android para instalar um exploit persistente. A partir daí, o invasor passa a ser o proprietário permanente do dispositivo e pode fazer qualquer coisa, incluindo desativar as atualizações.
A proteção contra essa classe de ataques é chamada de Proteção de rollback. A proteção contra reversão normalmente é implementada usando armazenamento inviolável para registrar a versão mais recente do Android e impedir a inicialização do 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 lida com proteções de rollback, consulte o README (link em inglês) do AVB.
Resolver erros de verificação
A verificação pode falhar durante a inicialização (por exemplo, se o hash calculado na partição
boot
não corresponder ao hash esperado) ou durante a execução
(por exemplo, se o dm-verity encontrar um erro de verificação na partição
system
). Se a verificação falhar na inicialização, o dispositivo
não poderá ser inicializado, e o usuário final precisará seguir etapas para recuperar o dispositivo.
Se a verificação falhar durante a execução, o fluxo será um pouco mais complicado. Se o
dispositivo usar 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 vai notar essa flag e mudar o dm-verity para usar o modo de erro de
E/S (eio
), permanecendo assim 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 uma corrupção e que o dispositivo pode não
funcionar corretamente. A tela aparece 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 ele.
O objetivo é 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 transferir o máximo de dados
do dispositivo possível. 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
.