Perfil do Aplicativo
O Perfil do Aplicativo é um mecanismo fornecido pelo KernelSU para personalizar a configuração de vários apps.
Para apps com privilégios root (ou seja, capazes de usar su
), o Perfil do Aplicativo também pode ser chamado de Perfil root. Ele permite a customização das regras uid
, gid
, grupos
, capacidades
e SELinux
do comando su
, restringindo assim os privilégios do usuário root. Por exemplo, ele pode conceder permissões de rede apenas para apps de firewall enquanto nega permissões de acesso a arquivos, ou pode conceder permissões de shell em vez de acesso root completo para apps congelados: mantendo o poder confinado com o princípio do menor privilégio.
Para apps comuns sem privilégios root, o Perfil do Aplicativo pode controlar o comportamento do kernel e do sistema de módulos em relação a esses apps. Por exemplo, pode determinar se as modificações resultantes dos módulos devem ser abordadas. O kernel e o sistema de módulos podem tomar decisões com base nesta configuração, como realizar operações semelhantes a "ocultar".
Perfil root
UID, GID e Grupos
Os sistemas Linux possuem dois conceitos: usuários e grupos. Cada usuário possui um ID de usuário (UID) e um usuário pode pertencer a vários grupos, cada um com seu próprio ID de grupo (GID). Esses IDs são usados para identificar usuários no sistema e determinar quais recursos do sistema eles podem acessar.
Os usuários com UID 0 são conhecidos como usuários root e os grupos com GID 0 são conhecidos como grupos root. O grupo de usuários root normalmente possui os privilégios de sistema mais altos.
No caso do sistema Android, cada app é um usuário separado (excluindo cenários de UID compartilhados) com um UID exclusivo. Por exemplo, 0
representa o usuário root, 1000
representa system
, 2000
representa o ADB shell e UIDs variando de 10.000
a 19.999
representam apps comuns.
INFORMAÇÕES
Aqui, o UID mencionado não é o mesmo que o conceito de múltiplos usuários ou perfis de trabalho no sistema Android. Os perfis de trabalho são, na verdade, implementados particionando o intervalo UID. Por exemplo, 10000-19999 representa o usuário principal, enquanto 110000-119999 representa um perfil de trabalho. Cada app comum entre eles possui seu próprio UID exclusivo.
Cada app pode ter vários grupos, com o GID representando o grupo principal, que geralmente corresponde ao UID. Outros grupos são conhecidos como grupos suplementares. Certas permissões são controladas por meio de grupos, como permissões de acesso à rede ou acesso Bluetooth.
Por exemplo, se executarmos o comando id
no ADB shell, a saída pode ser semelhante a esta:
oriole:/ $ id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readtracefs) context=u:r:shell:s0
Aqui, o UID é 2000
e o GID (ID do grupo primário) também é 2000
. Além disso, pertence a vários grupos suplementares, como inet
(indicando a capacidade de criar soquetes AF_INET
e AF_INET6
) e sdcard_rw
(indicando permissões de leitura/gravação para o cartão SD).
O Perfil root do KernelSU permite a personalização do UID, GID e grupos para o processo root após a execução de su
. Por exemplo, o Perfil root de um app root pode definir seu UID como 2000
, que significa que ao usar su
, as permissões reais do app estão no nível do ADB shell. O grupo inet
pode ser removido, evitando que o comando su
acesse a rede.
OBSERVAÇÃO
O Perfil do Aplicativo controla apenas as permissões do processo root após usar su
, e ele não controla as permissões do próprio app. Se um app solicitou permissão de acesso à rede, ele ainda poderá acessar a rede mesmo sem usar su
. Remover o grupo inet
de su
apenas impede que su
acesse a rede.
O Perfil root é aplicado no kernel e não depende do comportamento voluntário de apps root, ao contrário da troca de usuários ou grupos por meio de su
. A concessão da permissão su
depende inteiramente do usuário e não do desenvolvedor.
Capacidades
As capacidades são um mecanismo para separação de privilégios no Linux.
Para realizar verificações de permissão, as implementações tradicionais do UNIX
distinguem duas categorias de processos: processos privilegiados (cujo ID de usuário efetivo é 0
, referido como superusuário ou root) e processos sem privilégios (cujo UID efetivo é diferente de zero). Os processos privilegiados ignoram todas as verificações de permissão do kernel, enquanto os processos não privilegiados estão sujeitos à verificação completa de permissão com base nas credenciais do processo (geralmente: UID efetivo, GID efetivo e lista de grupos suplementares).
A partir do Linux 2.2, o Linux divide os privilégios tradicionalmente associados ao superusuário em unidades distintas, conhecidas como capacidades, que podem ser ativadas e desativadas de forma independente.
Cada capacidade representa um ou mais privilégios. Por exemplo, CAP_DAC_READ_SEARCH
representa a capacidade de ignorar verificações de permissão para leitura de arquivos, bem como permissões de leitura e execução de diretório. Se um usuário com um UID efetivo 0
(usuário root) não tiver recursos CAP_DAC_READ_SEARCH
ou superiores, isso significa que mesmo sendo root, ele não pode ler arquivos à vontade.
O Perfil root do KernelSU permite a personalização das capacidades do processo root após a execução de su
, conseguindo assim conceder parcialmente "privilégios root". Ao contrário do UID e GID mencionados acima, certos apps root exigem um UID de 0
após usar su
. Nesses casos, limitar as capacidades deste usuário root com UID 0
pode restringir suas operações permitidas.
FORTE RECOMENDAÇÃO
A documentação oficial da capacidade do Linux fornece explicações detalhadas das habilidades representadas por cada capacidade. Se você pretende customizar as capacidade, é altamente recomendável que você leia este documento primeiro.
SELinux
SELinux é um poderoso mecanismo do Controle de Acesso Obrigatório (MAC). Ele opera com base no princípio de negação padrão. Qualquer ação não explicitamente permitida é negada.
O SELinux pode ser executado em dois modos globais:
- Modo permissivo: Os eventos de negação são registrados, mas não aplicados.
- Modo de aplicação: Os eventos de negação são registrados e aplicados.
AVISO
Os sistemas Android modernos dependem fortemente do SELinux para garantir a segurança geral do sistema. É altamente recomendável não usar nenhum sistema personalizado executado em "Modo permissivo", pois não oferece vantagens significativas em relação a um sistema completamente aberto.
Explicar o conceito completo do SELinux é complexo e está além do objetivo deste documento. Recomenda-se primeiro entender seu funcionamento através dos seguintes recursos:
O Perfil root do KernelSU permite a personalização do contexto SELinux do processo root após a execução de su
. Regras específicas de controle de acesso podem ser definidas para este contexto para permitir um controle refinado sobre os privilégios root.
Em cenários típicos, quando um app executa su
, ele alterna o processo para um domínio SELinux com acesso irrestrito, como u:r:su:s0
. Através do Perfil root, este domínio pode ser mudado para um domínio personalizado, como u:r:app1:s0
, e uma série de regras podem ser definidas para este domínio:
type app1
enforce app1
typeattribute app1 mlstrustedsubject
allow app1 * * *
Observe que a regra allow app1 * * *
é usada apenas para fins de demonstração. Na prática, esta regra não deve ser utilizada extensivamente, pois não difere muito do Modo permissivo.
Escalação
Se a configuração do Perfil root não estiver definida corretamente, poderá ocorrer um cenário de escalação. As restrições impostas pelo Perfil root poderão falhar involuntariamente.
Por exemplo, se você conceder permissão root a um usuário ADB shell (que é um caso comum) e, em seguida, conceder permissão root a um app normal, mas configurar seu Perfil root com UID 2000 (que é o UID do usuário ADB shell), o app pode obter acesso root completo executando o comando su
duas vezes:
- A primeira execução
su
está sujeita à aplicação do Perfil do Aplicativo e mudará para UID2000
(ADB shell) em vez de0
(root). - A segunda execução
su
, como o UID é2000
e você concedeu acesso root ao UID2000
(ADB shell) na configuração, o app obterá privilégios root completo.
OBSERVAÇÃO
Este comportamento é totalmente esperado e não é um bug. Portanto, recomendamos o seguinte:
Se você realmente precisa conceder privilégios root ao ADB (por exemplo, como desenvolvedor), não é aconselhável alterar o UID para 2000
ao configurar o Perfil root. Usar 1000
(system) seria uma melhor escolha.
Perfil não root
Desmontar módulos
O KernelSU fornece um mecanismo sem sistema para modificar partições do sistema, obtido através da montagem de OverlayFS. No entanto, alguns apps podem ser sensíveis a esse comportamento. Assim, podemos descarregar módulos montados nesses apps configurando a opção "Desmontar módulos".
Além disso, a interface de configurações do gerenciador do KernelSU fornece uma opção para "Desmontar módulos por padrão". Por padrão, essa opção está ativada, o que significa que o KernelSU ou alguns módulos descarregarão módulos para este app, a menos que configurações adicionais sejam aplicadas. Se você não preferir esta configuração ou se ela afetar determinados apps, você terá as seguintes opções:
- Mantenha a opção "Desmontar módulos por padrão" e desative individualmente a opção "Desmontar módulos" no Perfil do Aplicativo para apps que exigem carregamento do módulo (agindo como uma "lista de permissões").
- Desative a opção "Desmontar módulos por padrão" e ative individualmente a opção "Desmontar módulos" no Perfil do Aplicativo para apps que exigem descarregamento do módulo (agindo como uma "lista negra").
INFORMAÇÕES
Em dispositivos que utilizam a versão do kernel 5.10 e superior, o kernel realiza qualquer ação adicional do descarregamento de módulos. No entanto, para dispositivos que executam versões do kernel abaixo de 5.10, essa opção é apenas uma opção de configuração e o próprio KernelSU não executa nenhuma ação. Se você quiser usar a opção "Desmontar módulos" em versões do kernel anteriores a 5.10 você precisa portar a função path_umount
em fs/namespace.c
, você pode obter mais informações no final da página Como integrar o KernelSU para kernels não GKI. Alguns módulos, como ZygiskNext, também podem usar essa opção para determinar se o descarregamento do módulo é necessário.