A Google recomenda reduzir a superfície de ataque das unidades de processamento gráfico no Android restringindo os comandos IOCTL de que os aplicativos não precisam em um ambiente de produção, em vez de depender apenas da descoberta e correção de vulnerabilidades individuais. Essa prática resulta de uma colaboração entre a equipe Android Red Team e a Arm para analisar a GPU Mali e seu driver, com foco em impedir o acesso a funções desnecessárias usando o SELinux.
Essa medida tem importância para a segurança porque a unidade de processamento gráfico se tornou um alvo atraente para invasores devido à sua complexidade e às permissões elevadas que possui dentro do sistema. De acordo com o material, a maioria das explorações baseadas em drivers do kernel do Android desde 2021 teve como alvo a unidade de processamento gráfico, e os ataques se concentraram principalmente na interface entre o driver em modo de usuário, conhecido como UMD, e o driver com permissões elevadas em modo kernel, ou KMD.
Por que reduzir a superfície de ataque é uma prioridade?
Entradas maliciosas que passam por essa interface podem explorar falhas que causam corrupção de memória. A Google considera que tornar os caminhos desnecessários inacessíveis oferece uma maneira eficaz e, muitas vezes, mais rápida de elevar o nível de proteção, paralelamente à continuidade da descoberta e correção de bugs.
A análise conjunta com a Arm incluiu o driver Mali usado em cerca de 45% dos dispositivos Android e ajudou a identificar partes da superfície de ataque que representam riscos de segurança, mas não são necessárias para operar os dispositivos em produção. Com base nisso, a política se concentrou nos comandos IOCTL, que representam as entradas e saídas do driver da unidade de processamento gráfico e, portanto, uma parte importante da superfície de ataque.
O método proposto divide os comandos Mali em três categorias:
- Comandos não restritos: necessários para a operação normal e continuam disponíveis para os aplicativos.
- Comandos de medição e ferramentas: usados por ferramentas de análise de desempenho e depuração para monitorar o desempenho da unidade de processamento gráfico.
- Comandos restritos: não devem ser usados por aplicativos de produção e incluem comandos destinados ao desenvolvimento da unidade de processamento gráfico, além de comandos antigos que não são mais usados na versão atual do UMD do dispositivo.
A política tem como objetivo bloquear comandos antigos e de depuração no ambiente de produção, limitando os comandos de medição ao shell ou a aplicativos marcados como depuráveis. Já os comandos de produção permanecem disponíveis para aplicativos comuns.
Implementação gradual da política SELinux
A Google adotou uma abordagem gradual para reduzir a possibilidade de desativar aplicativos legítimos. O processo começou com uma política opcional e criou um novo atributo SELinux chamado gpu_harden, que impede comandos de medição, aplicando-o depois a um conjunto específico de aplicativos do sistema para testar seu impacto. Durante essa fase, foi usada a regra allowxperm para registrar tentativas de acesso em vez de bloqueá-las diretamente; em seguida, os registros de negação foram monitorados para verificar a ausência de falhas.
Depois de confirmar a segurança da abordagem, a política passou para um modelo padrão mais rigoroso, com a criação de um domínio chamado gpu_debug que permite o acesso aos comandos de medição. Assim, os aplicativos passaram a ser protegidos por padrão, com exceções disponíveis para desenvolvedores em casos específicos:
- Executar o aplicativo em um dispositivo com permissões de root.
- Definir a propriedade android:debuggable="true" no manifesto do aplicativo.
- Solicitar uma exceção permanente na política SELinux específica do aplicativo.
Etapas para aplicar a política aos dispositivos
A Google fornece orientações para ajudar parceiros e o ecossistema mais amplo a adotar um mecanismo semelhante, separando a lógica da política geral dos detalhes de cada dispositivo ou driver. O processo começa com o uso de um módulo de macro geral no nível da plataforma Android, em system/sepolicy. Esse módulo está no arquivo /sepolicy/public/te_macros e permite que as políticas dos dispositivos passem listas de comandos IOCTL que devem ser filtrados.
O módulo foi projetado para permitir que todos os aplicativos, ou appdomain, acessem a lista de comandos não restritos e para limitar os comandos de medição sensíveis a ferramentas de depuração, como shell ou runas_app, quando o aplicativo for depurável. Ele também bloqueia comandos com permissões elevadas com base na versão do SDK de destino do aplicativo, mantendo a compatibilidade com aplicativos mais antigos.
Depois disso, o desenvolvedor do dispositivo cria um arquivo ioctl_macros dentro da pasta de política SELinux específica do dispositivo, como device/your_company/your_device/sepolicy/ioctl_macros, e então define as listas de comandos específicas do driver da unidade de processamento gráfico. A Google recomenda ter pelo menos listas separadas para comandos de produção, comandos de medição e comandos de depuração, contendo os números hexadecimais de IOCTL específicos do driver.
A Arm forneceu uma classificação oficial dos seus comandos IOCTL no arquivo Documentation/ioctl-categories.rst, incluído na versão r54p2, observando que a lista continuará sendo atualizada com futuras versões dos drivers.
Testes antes da aplicação obrigatória
Na etapa seguinte, a política é aplicada ao nó do dispositivo da unidade de processamento gráfico por meio da criação de um arquivo gpu.te na pasta de política do dispositivo; depois, o módulo de macro geral é chamado e recebe a etiqueta do dispositivo e as listas de IOCTL previamente definidas.
A Google enfatiza que o desenvolvimento de uma política SELinux deve continuar sendo um processo iterativo que inclui testes, refinamento e, depois, aplicação obrigatória. Esse método permite coletar dados de uso real, identificar situações que possam exigir exceções e ampliar gradualmente o alcance da política, em vez de impor restrições amplas desde o início.
A Google considera que reduzir a superfície de ataque não protege apenas contra vulnerabilidades conhecidas, mas também pode tornar inacessíveis, por meio dos caminhos restritos, vulnerabilidades ainda não descobertas ou que possam surgir no futuro. A ampliação dessa abordagem exige colaboração entre o Android, os fabricantes de dispositivos e os parceiros do ecossistema, enquanto as equipes de segurança do Android afirmaram estar comprometidas em apoiar a adoção dessas medidas em maior escala.