Conceitos do SELinux

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 um sistema MAC, ele difere do conhecido sistema de controle de acesso discricionário (DAC) do Linux. Em um 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 uma escalada de privilégios não intencional. Um sistema MAC, no entanto, consulta uma autoridade central para uma decisão sobre todas as tentativas de acesso.

O SELinux foi implementado como parte da estrutura do Linux Security Module (LSM), que reconhece vários objetos do kernel e as 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 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 obrigatórios e discricionários do Android oferece uma estrutura para garantir que seu software seja executado apenas no nível de privilégio mínimo. Isso atenua os efeitos dos ataques e reduz a probabilidade de processos errados sobrescreverem ou 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 a conta de usuário root para gravar em dispositivos de bloco bruto. Em um ambiente Linux tradicional baseado em DAC, se o usuário root for comprometido, esse usuário poderá gravar em cada dispositivo de bloco bruto. No entanto, o SELinux pode ser usado para rotular esses dispositivos para que o processo atribuído ao privilégio de 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 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.
  • Aplicação - A política de segurança é aplicada e registrada. As falhas aparecem como erros EPERM.

Essa escolha é binária e determina se sua política age ou simplesmente permite que você colete possíveis falhas. Permissivo é especialmente útil durante a implementação.

Tipos, atributos e regras

O Android conta com o componente Type Enforcement (TE) do SELinux para sua 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 aplicativo terá o tipo untrusted_app . Para um processo, seu tipo também é conhecido como seu domínio . É possível anotar um tipo com um ou vários atributos . Os atributos são úteis para fazer referência 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 socket) e os diferentes tipos de acesso para cada classe são representados por permissions . Por exemplo, a permissão open existe para o file de classe . Embora tipos e atributos sejam atualizados regularmente como parte da política do Android SELinux, 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 na forma: allow source target : class permissions ; Onde:

  • Origem - O tipo (ou atributo) do assunto da regra. Quem está solicitando o acesso?
  • Destino - O tipo (ou atributo) do objeto. A que se solicita 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 diz que os aplicativos têm permissão para ler e gravar arquivos rotulados como app_data_file . Existem outros tipos de aplicativos. Para instâncias, 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 uma regra é escrita 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

Para acesso a arquivos em particular, há muitos tipos de permissão a serem considerados. Por exemplo, a permissão de read não é suficiente para abrir o arquivo ou chamar stat nele. Para simplificar a definição da regra, 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 pode ser reescrita como:

allow appdomain app_data_file:file rw_file_perms;

Veja os arquivos global_macros e te_macros 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 de permissões relacionadas.

Uma vez que um tipo é definido, ele precisa ser associado ao arquivo ou processo que ele representa. Consulte Implementando o SELinux para obter mais detalhes sobre como essa associação é feita. Para obter mais informações sobre regras, consulte o SELinux Notebook .

Contexto e categorias de segurança

Ao depurar políticas SELinux ou rotular arquivos (via file_contexts ou ao executar ls -Z ), você pode encontrar 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] . Normalmente, 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 de segurança multinível (MLS) no SELinux. Desde o Android S, as categorias são usadas para:

  • Isole os dados do aplicativo do acesso por 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, lembre-se destes pontos:

  • A maioria das políticas no AOSP são definidas usando o Kernel Policy Language. Existem algumas exceções para o uso da 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 usando o campo de categorias de um contexto de segurança.
  • As funções do SELinux e o controle de acesso baseado em função (RBAC) 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 é sempre definida.
  • Os booleanos do SELinux não são usados. Depois que 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.