Conceitos do SELinux

Leia esta página para se familiarizar com os conceitos do SELinux.

Controle de acesso obrigatório

O Security Enhanced Linux (SELinux) é um sistema de controle de acesso obrigatório (MAC, na sigla em inglês) para o sistema operacional Linux. Como um sistema MAC, ele é diferente do sistema de controle de acesso discricionário (DAC, na sigla em inglês) do Linux. Em um sistema DAC, existe um conceito de propriedade, em que o proprietário de um recurso específico controla as permissões de acesso associadas a ele. Isso geralmente é de granularidade grosseira e sujeito a escalonamento de privilégios não intencional. No entanto, um sistema MAC consulta uma autoridade central para tomar uma decisão sobre todas as tentativas de acesso.

O SELinux foi implementado como parte do framework do módulo de segurança do Linux (LSM, na sigla em inglês), que reconhece vários objetos do kernel e ações confidenciais realizadas neles. No momento em que cada uma dessas ações seria realizada, uma função de hook do LSM é chamada para determinar se a ação deve ser permitida ou não com base nas informações armazenadas em um objeto de segurança opaco. O SELinux fornece uma implementação para esses hooks e o gerenciamento desses objetos de segurança, que se combinam com a própria política para determinar as decisões de acesso.

Junto com outras medidas de segurança do Android, a política de controle de acesso do Android limita muito os possíveis danos de máquinas e contas comprometidas. O uso de ferramentas como os controles de acesso discricionários e obrigatórios do Android oferece uma estrutura para garantir que o software seja executado apenas no nível de privilégio mínimo. Isso atenua os efeitos de ataques e reduz a probabilidade de processos errôneos substituírem ou até mesmo transmitirem dados.

No Android 4.3 e versões mais recentes, o SELinux oferece um controle de acesso obrigatório (MAC) sobre ambientes tradicionais de controle de acesso discricionário (DAC). Por exemplo, o software geralmente precisa ser executado como a conta de usuário raiz para gravar em dispositivos de bloco brutos. Em um ambiente Linux tradicional baseado em DAC, se o usuário raiz for comprometido, ele poderá gravar em todos os dispositivos de bloco brutos. No entanto, o SELinux pode ser usado para rotular esses dispositivos para que o processo atribuído ao privilégio raiz 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 mais exemplos de ameaças e maneiras de resolvê-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.
  • Aplicando : a política de segurança é aplicada e registrada. As falhas aparecem como erros EPERM.

Essa escolha é binária e determina se a política entra em ação ou apenas permite que você colete possíveis falhas. O modo permissivo é especialmente útil durante a implementação.

Tipos, atributos e regras

O Android depende do componente de aplicação de tipo (TE, na sigla em inglês) do SELinux para a política. Isso significa que todos os objetos (como arquivo, processo ou soquete) têm um tipo associado a eles. Por exemplo, por padrão, um app tem o tipo untrusted_app. Para um processo, o 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, a permissão open existe para a classe file. Embora os tipos e atributos sejam atualizados regularmente como parte da política do 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 tem o formato: allow source target:class permissions; em que:

  • Source : o tipo (ou atributo) do assunto da regra. Quem está solicitando o acesso?
  • Target : o tipo (ou atributo) do objeto. Para o que o acesso é solicitado?
  • Class : o tipo de objeto (por exemplo, arquivo, soquete) que está sendo acessado.
  • Permissões : a operação (ou conjunto de operações) (por exemplo, ler, gravar) que está sendo realizada.

Um exemplo de regra é:

allow untrusted_app app_data_file:file { read write };

Isso significa que os apps podem ler e gravar arquivos rotulados como app_data_file. Existem outros tipos de apps. Por exemplo, isolated_app é usado para serviços de app com isolatedProcess=true no manifesto. Em vez de repetir a regra para os dois tipos, o Android usa um atributo chamado appdomain para todos os tipos que abrangem apps:

# 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 uma regra é escrita que especifica um nome de atributo, esse nome é expandido automaticamente 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 processo.
  • file_type: atributo associado a todos os tipos de arquivo.

Macros

Para acesso a arquivos em particular, 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 oferece um conjunto de macros para lidar com os casos mais comuns. Por exemplo, para incluir as permissões ausentes, como open, a regra acima pode ser reescrita como:

allow appdomain app_data_file:file rw_file_perms;

Consulte os global_macros e te_macros arquivos para mais exemplos de macros úteis. As macros devem ser usadas sempre que possível para ajudar a reduzir a probabilidade de falhas devido a negações em permissões relacionadas.

Depois que um tipo é definido, ele precisa ser associado ao arquivo ou processo que representa. Consulte Implementar o SELinux para mais detalhes sobre como essa associação é feita. Para mais informações sobre regras, consulte o SELinux Notebook (link em inglês).

Contexto e categorias de segurança

Ao depurar políticas do SELinux ou rotular arquivos (usando file_contexts ou ls -Z), você pode encontrar um contexto de segurança (também conhecido como rótulo). 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, é possível 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 de segurança de vários níveis (MLS, na sigla em inglês) no SELinux. No Android 12 e versões mais recentes, as categorias são usadas para:

  • Isolar os dados do app do acesso por outro app.
  • Isolar os dados do app de um usuário físico para outro.

Especificidade

O Android não usa todos os recursos fornecidos pelo SELinux. Ao ler documentação externa, tenha estes pontos em mente:

  • A maioria das políticas no AOSP é definida usando a linguagem de política do kernel. Há algumas exceções para o uso da linguagem intermediária comum (CIL, na sigla em inglês).
  • 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 usando o campo de categorias de um contexto de segurança.
  • As funções do SELinux e o controle de acesso baseado em papéis (RBAC, na sigla em inglês) não são usados. Duas funções padrão são definidas e usadas: r para assuntos e object_r para objetos.
  • As sensibilidades do SELinux não são usadas. A sensibilidade s0 padrão está sempre definida.
  • Os booleanos do SELinux não são usados. Quando a política é criada para um dispositivo, ela não depende do estado do dispositivo. Isso simplifica a auditoria e a depuração de políticas.