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 familiar 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 determinado recurso controla as permissões de acesso associadas a ele. Isso geralmente é grosseiro e sujeito a escalonamento 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 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 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ário e obrigatório do Android fornece uma estrutura para garantir que seu software seja executado apenas no nível mínimo de privilégio. Isso mitiga 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 controle de acesso obrigatório (MAC) sobre os ambientes tradicionais de controle de acesso discricionário (DAC). Por exemplo, o software normalmente deve ser executado como a conta de usuário raiz para gravar em dispositivos de bloco bruto. Em um ambiente Linux tradicional baseado em DAC, se o usuário raiz for comprometido, esse usuário poderá gravar em todos os dispositivos de bloco bruto. No entanto, o SELinux pode ser usado para rotular esses dispositivos para que o processo atribuído ao privilégio root possa gravar apenas naqueles especificados na política associada. Dessa forma, o processo não pode sobrescrever 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 tratá-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 entra em ação ou apenas permite que você reúna 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 mais 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 o file de classe . Embora os tipos e atributos sejam atualizados regularmente como parte da política do Android SELinux, 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:

  • Origem - O tipo (ou atributo) do assunto da regra. Quem está solicitando o acesso?
  • Alvo - 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 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 especificando 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 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;

Consulte os arquivos global_macros e te_macros para obter 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.

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

Contexto e categorias de segurança

Ao depurar políticas do SELinux ou rotular arquivos (via file_contexts ou quando 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 Multi-Level Security (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, tenha em mente estes pontos:

  • A maioria das políticas no AOSP são definidas usando o Kernel Policy Language. Existem algumas exceções para o uso do Common Intermediate Language (CIL).
  • 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 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.