Raiz é usuário 0
A principal coisa é o ID do usuário 0. Existem muitos lugares no kernel que verificam o ID do usuário do processo de chamada e concedem permissão para fazer algo apenas se o ID do usuário for 0.
O nome do usuário é irrelevante; o kernel nem sabe sobre nomes de usuários.
O mecanismo de permissão do Android é idêntico no nível do kernel, mas completamente diferente no nível do aplicativo. O Android tem um usuário root (UID 0), assim como qualquer outro sistema baseado em um kernel Linux. O Android não tem contas de usuário, e na maioria das configurações não permite que o usuário (como no ser humano que opera e possui o dispositivo) execute ações como o usuário root. Um Android "enraizado" é uma configuração que permite que o proprietário / usuário do dispositivo execute ações como root.
Como funciona o setuid
Um executável setuid é executado como o usuário que possui o executável. Por exemplo, su
é setuid e pertence a root, portanto, quando qualquer usuário o executa, o processo executando su
é executado como usuário root. O trabalho de su
é verificar se o usuário que o chama tem permissão para usar a conta raiz, executar o comando especificado (ou um shell se nenhum comando for especificado) se essa verificação for bem-sucedida e sair se essa verificação falhar . Por exemplo, su
pode pedir ao usuário para provar que conhece a senha do root.
Mais detalhadamente, um processo tem três IDs de usuário : o eficaz UID , que é usado para verificações de segurança; o real UID, que é usado em algumas verificações de privilégio, mas é principalmente útil como backup do ID do usuário original e do ID do usuário salvo que permite que um processo mude temporariamente seu UID efetivo para o real ID do usuário e, em seguida, voltar ao antigo UID efetivo (isso é útil, por exemplo, quando um programa setuid precisa acessar um arquivo como o usuário original). A execução de um executável setuid define o UID efetivo para o proprietário do executável e mantém o UID real.
A execução de um executável setuid (e mecanismos semelhantes, por exemplo, setgid) é a única maneira de elevar os privilégios de um processo. Quase tudo o resto só pode diminuir os privilégios de um processo.
Além do Unix tradicional
Até agora eu descrevi sistemas tradicionais Unix. Tudo isso é verdade em um sistema Linux moderno, mas o Linux traz várias complicações adicionais.
O Linux tem um sistema de capacidade . Lembre-se de como eu disse que o kernel tem muitas verificações onde apenas os processos em execução como ID de usuário 0 são permitidos? Na verdade, cada cheque recebe seu próprio recurso (bem, não é bem assim, algumas verificações usam o mesmo recurso). Por exemplo, há um recurso para acessar soquetes de rede brutos e outro recurso para reinicializar o sistema. Cada processo tem um conjunto de recursos ao lado de seus usuários e grupos. O processo passa a verificação se estiver executando como usuário 0 ou se tiver a capacidade correspondente à verificação. Um processo que requer um privilégio específico pode ser executado como um usuário não raiz, mas com o recurso necessário; isso limita o impacto se o processo tiver uma falha de segurança. Um executável pode ser setcap para um ou mais recursos: isso é semelhante ao setuid, mas funciona no conjunto de recursos do processo em vez do ID do usuário do processo. Por exemplo, o ping só precisa de soquetes de rede brutos, então pode ser setcap CAP_NET_RAW
em vez de setuid root.
O Linux tem vários módulos de segurança , sendo o mais conhecido SELinux . Os módulos de segurança introduzem verificações de segurança adicionais, que podem ser aplicadas até mesmo a processos em execução como raiz. Por exemplo, é possível (não fácil!) Configurar o SELinux para executar um processo como o ID do usuário 0, mas com tantas restrições que não pode realmente fazer nada .
O Linux tem namespaces de usuário . Dentro do kernel, um usuário não é apenas um ID do usuário, mas um par que consiste em um ID do usuário e um namespace. Os namespaces formam uma hierarquia: um namespace filho refina as permissões dentro de seu pai. O usuário todo poderoso é o usuário 0 no namespace raiz. O usuário 0 em um namespace tem poderes apenas dentro desse namespace. Por exemplo, o usuário 0 em um namespace de usuário pode representar qualquer usuário desse namespace; mas do lado de fora todos os processos nesse namespace são executados como o mesmo usuário.