Revise esta página para se familiarizar com os conceitos do SELinux.
Controle de acesso obrigatório
Security Enhanced Linux (SELinux), é um sistema de controle de acesso obrigatório (MAC) para o sistema operacional Linux. Como sistema MAC, ele difere do familiar sistema de controle de acesso discricionário (DAC) do Linux. Num sistema DAC, existe um conceito de propriedade, pelo qual um proprietário de um recurso específico controla as permissões de acesso associadas a ele. Isso geralmente é grosseiro e está sujeito a escalonamento de privilégios não intencional. Um sistema MAC, entretanto, consulta uma autoridade central para tomar uma decisão sobre todas as tentativas de acesso.
SELinux foi implementado como parte da estrutura Linux Security Module (LSM), que reconhece vários objetos do kernel e ações confidenciais executadas neles. No ponto em que cada uma dessas ações seria executada, uma função de gancho LSM é chamada para determinar se a ação deve ou não ser permitida com base nas informações armazenadas em um objeto de segurança opaco. O SELinux fornece uma implementação para esses ganchos e gerenciamento desses objetos de segurança, que se combinam com sua própria política, para determinar as decisões de acesso.
Juntamente com outras medidas de segurança do Android, a política de controle de acesso do Android limita bastante o dano potencial de máquinas e contas comprometidas. O uso de ferramentas como os controles de acesso discricionários e obrigatórios do Android fornece uma estrutura para garantir que seu software seja executado apenas no nível mínimo de privilégio. Isso atenua os efeitos dos ataques e reduz a probabilidade de processos errôneos sobrescreverem ou até mesmo transmitirem dados.
No Android 4.3 e superior, o SELinux fornece um guarda-chuva de controle de acesso obrigatório (MAC) sobre ambientes tradicionais de controle de acesso discricionário (DAC). Por exemplo, o software normalmente deve ser executado como conta de usuário root para gravar em dispositivos de bloco brutos. Em um ambiente Linux tradicional baseado em DAC, se o usuário root for comprometido, ele poderá gravar em cada dispositivo de bloco bruto. No entanto, o SELinux pode ser usado para rotular esses dispositivos para que o processo ao qual foi atribuído o privilégio root possa gravar apenas naqueles especificados na política associada. Dessa forma, o processo não pode substituir dados e configurações do sistema fora do dispositivo de bloco bruto específico.
Consulte Casos de uso para obter mais exemplos de ameaças e maneiras de enfrentá-las com o SELinux.
Níveis de aplicação
O SELinux pode ser implementado em vários modos:
- Permissivo - a política de segurança do SELinux não é aplicada, apenas registrada.
- Aplicação – A política de segurança é aplicada e registrada. As falhas aparecem como erros EPERM.
Esta escolha é binária e determina se a sua política entra em acção ou apenas permite recolher potenciais falhas. Permissivo é especialmente útil durante a implementação.
Tipos, atributos e regras
O Android depende do componente Type Enforcement (TE) do SELinux para sua política. Isso significa que todos os objetos (como arquivo, processo ou soquete) possuem um tipo associado a eles. Por exemplo, por padrão, um aplicativo terá o tipo untrusted_app
. Para um processo, seu tipo também é conhecido como domínio . É possível anotar um tipo com um ou vários atributos . Os atributos são úteis para se referir a vários tipos ao mesmo tempo.
Os objetos são mapeados para classes (por exemplo, um arquivo, um diretório, um link simbólico, um soquete) e os diferentes tipos de acesso para cada classe são representados por permissões . Por exemplo, existe a permissão open
para o file
de classe. Embora os tipos e atributos sejam atualizados regularmente como parte da política SELinux do Android, as permissões e classes são definidas estaticamente e raramente atualizadas como parte de uma nova versão do Linux.
Uma regra de política vem no formato: allow source target : class permissions ;
onde:
- Fonte – O tipo (ou atributo) do assunto da regra. Quem está solicitando o acesso?
- Destino - O tipo (ou atributo) do objeto. Para que é solicitado o acesso?
- Classe - O tipo de objeto (por exemplo, arquivo, soquete) que está sendo acessado.
- Permissões - A operação (ou conjunto de operações) (por exemplo, leitura, gravação) que está sendo executada.
Um exemplo de regra é:
allow untrusted_app app_data_file:file { read write };
Isso indica que os aplicativos têm permissão para ler e gravar arquivos rotulados como app_data_file
. Existem outros tipos de aplicativos. Por exemplo, isolated_app
é usado para serviços de aplicativo com isolatedProcess=true
em seu manifesto. Em vez de repetir a regra para ambos os tipos, o Android usa um atributo chamado appdomain
para todos os tipos que abrangem aplicativos:
# Associate the attribute appdomain with the type untrusted_app. typeattribute untrusted_app, appdomain; # Associate the attribute appdomain with the type isolated_app. typeattribute isolated_app, appdomain; allow appdomain app_data_file:file { read write };
Quando é escrita uma regra que especifica um nome de atributo, esse nome é automaticamente expandido para a lista de domínios ou tipos associados ao atributo. Alguns atributos notáveis são:
-
domain
- atributo associado a todos os tipos de processos, -
file_type
- atributo associado a todos os tipos de arquivo.
Macros
Especialmente para acesso a arquivos, há muitos tipos de permissão a serem considerados. Por exemplo, a permissão read
não é suficiente para abrir o arquivo ou chamar stat
nele. Para simplificar a definição de regras, o Android fornece um conjunto de macros para lidar com os casos mais comuns. Por exemplo, para incluir as permissões ausentes, como open
, a regra acima poderia ser reescrita como:
allow appdomain app_data_file:file rw_file_perms;
Consulte os arquivos global_macros
e te_macros
para obter mais exemplos de macros úteis. Macros devem ser usadas sempre que possível para ajudar a reduzir a probabilidade de falhas devido a negações de permissões relacionadas.
Depois que um tipo é definido, ele precisa ser associado ao arquivo ou processo que representa. Veja Implementando o SELinux para mais detalhes de como essa associação é feita. Para obter mais informações sobre regras, consulte o Notebook SELinux .
Contexto e categorias de segurança
Ao depurar políticas SELinux ou rotular arquivos (via file_contexts
ou ao usar ls -Z
), você pode se deparar com um contexto de segurança (também conhecido como label ). Por exemplo: u:r:untrusted_app:s0:c15,c256,c513,c768
. Um contexto de segurança tem o formato: user:role:type:sensitivity[:categories]
. Geralmente você pode ignorar os campos user
, role
e sensitivity
de um contexto (consulte Especificidade ). O campo type
é explicado na seção anterior. categories
fazem parte do suporte Multi-Level Security (MLS) no SELinux. Desde o Android S, as categorias são usadas para:
- Isole os dados do aplicativo do acesso de outro aplicativo,
- Isole os dados do aplicativo de um usuário físico para outro.
Especificidade
O Android não usa todos os recursos fornecidos pelo SELinux. Ao ler a documentação externa, tenha em mente estes pontos:
- A maioria das políticas no AOSP são definidas usando a Kernel Policy Language. Existem algumas exceções para o uso de Common Intermediate Language (CIL).
- Os usuários do SELinux não são usados. O único usuário definido é
u
. Quando necessário, os usuários físicos são representados através do campo de categorias de um contexto de segurança. - As funções SELinux e o Role-Based Access Control (RBAC) não são usados. Duas funções padrão são definidas e usadas:
r
para assuntos eobject_r
para objetos. - As sensibilidades do SELinux não são usadas. A sensibilidade
s0
padrão está sempre definida. - Os booleanos SELinux não são usados. Depois que a política for criada para um dispositivo, ela não dependerá do estado do dispositivo. Isso simplifica a auditoria e a depuração de políticas.