Como implementar o SELinux

O SELinux está configurado para negação por padrão, o que significa que cada acesso que tem um hook no kernel, precisa ser explicitamente permitido pela política. Isso significa que um arquivo de política é composto por uma grande quantidade de informações sobre regras, tipos, classes, permissões e muito mais. Uma consideração completa do SELinux está fora do escopo deste documento, mas entender como escrever as regras de política agora são essenciais ao criar novos dispositivos Android. Há um grande quantidade de informações disponíveis sobre o SELinux. Consulte Suporte documentação para recursos sugeridos.

Arquivos de chaves

Para ativar o SELinux, integre a mais recente kernel do Android e depois incorpora os arquivos encontrados na system/sepolicy (link em inglês) diretório. Quando compilados, esses arquivos formam a parte de segurança do kernel e abrangem o sistema operacional Android upstream.

Em geral, não modifique os arquivos system/sepolicy diretamente. Adicione ou edite seus próprios arquivos de política específicos do dispositivo na /device/manufacturer/device-name/sepolicy diretório. No Android 8.0 e versões mais recentes, as alterações feitas nesses arquivos devem afetam apenas a política no seu diretório de fornecedores. Para mais detalhes sobre a separação sepolicy pública no Android 8.0 e superior, consulte Como personalizar o SEPolicy no Android 8.0 ou superior. Independentemente da versão do Android, você ainda está modificando estes arquivos:

Arquivos de política

Os arquivos que terminam com *.te são arquivos de origem de políticas do SELinux, que definem os domínios e os rótulos. Talvez seja necessário criar novos arquivos de política no /device/manufacturer/device-name/sepolicy, mas tente atualizar os arquivos existentes sempre que possível.

Arquivos de contexto

Nos arquivos de contexto, são especificados rótulos para os objetos.

  • O file_contexts atribui marcadores a arquivos e é usado por vários componentes de espaço do usuário. Ao criar novas políticas, crie ou atualize este arquivo atribuir novos marcadores aos arquivos. Para aplicar os novos file_contexts, recrie a imagem do sistema de arquivos ou execute restorecon no arquivo para ser remarcados. Em upgrades, as mudanças em file_contexts são são aplicadas automaticamente às partições do sistema e dos dados do usuário como parte da e fazer o upgrade. As mudanças também podem ser aplicadas automaticamente no upgrade para outros partições adicionando chamadas restorecon_recursive às arquivo init.board.rc após a montagem da partição. leitura-gravação.
  • O genfs_contexts atribui rótulos aos sistemas de arquivos, como proc ou vfat que não são compatíveis com a extensão atributos. Essa configuração é carregada como parte da política do kernel, mas alterações podem não entrar em vigor para inodes no núcleo, exigindo uma reinicialização ou desmontando e remontando o sistema de arquivos para aplicar totalmente a alteração. Rótulos específicos também podem ser atribuídos a suportes específicos, como vfat usando a opção context=mount.
  • O property_contexts atribui rótulos às propriedades do sistema Android para: e controlar quais processos podem defini-los. Essa configuração é lida pelo Processo init durante a inicialização.
  • service_contexts atribui rótulos aos serviços de vinculação do Android para controlar quais processos podem adicionar (registrar) e encontrar (procurar) um binder para o serviço. Essa configuração é lida pelo Processo servicemanager durante a inicialização.
  • seapp_contexts atribui identificadores a processos de apps e /data/data. Essa configuração é lida pelo zygote a cada inicialização do app e até installd durante a inicialização.
  • mac_permissions.xml atribui uma tag seinfo aos apps com base na assinatura e, opcionalmente, no nome do pacote. A A tag seinfo pode ser usada como uma chave na Arquivo seapp_contexts para atribuir um marcador específico a todos os apps com a tag seinfo. Essa configuração é lida system_server durante a inicialização.
  • keystore2_key_contexts atribui rótulos aos namespaces do Keystore 2.0. Esse namespace é aplicado pelo daemon keystore2. O Keystore sempre os namespaces fornecidos com base em UID/AID. O Keystore 2.0 também aplica sepolicy os namespaces definidos. Uma descrição detalhada do formato e das convenções desta pode ser encontrado aqui.

Makefile do BoardConfig.mk

Depois de editar ou adicionar os arquivos de política e contexto, atualize o /device/manufacturer/device-name/BoardConfig.mk makefile para fazer referência ao subdiretório sepolicy e a cada novo arquivo de política. Para mais informações sobre as variáveis BOARD_SEPOLICY, consulte arquivo system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Após a recriação, o dispositivo será ativado com o SELinux. Agora é possível personalizar suas políticas de SELinux para acomodar suas próprias adições ao Sistema operacional Android, conforme descrito em Personalização ou verifique sua configuração atual conforme abordado nas Validação.

Quando os novos arquivos de política e as atualizações do BoardConfig.mk estiverem prontos, os novos as configurações de política são incorporadas automaticamente ao arquivo de política do kernel final. Para mais informações sobre como o sepolicy é criado no dispositivo, consulte Como criar sepolicy.

Implementação

Para começar a usar o SELinux:

  1. Ative o SELinux no kernel: CONFIG_SECURITY_SELINUX=y
  2. Altere o parâmetro kernel_cmdline ou bootconfig para que:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    ou
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Isso serve apenas para o desenvolvimento inicial da política para o dispositivo. Depois de tiver uma política de inicialização inicial, remova esse parâmetro para que dispositivo está aplicando ou falhará no CTS.
  3. Inicialize o sistema como permissivo e confira quais negações são encontradas na inicialização:
    No Ubuntu 14.04 ou mais recente:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    No Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Avalie a saída de avisos semelhantes a init: Warning! Service name needs a SELinux domain defined; please fix!. Consulte Validação para instruções e ferramentas.
  5. Identifique dispositivos e outros arquivos novos que precisam de rotulagem.
  6. Use rótulos novos ou atuais para seus objetos. Observe o *_contexts arquivos para saber como os itens eram rotulados anteriormente e usar o conhecimento dos significados dos rótulos para atribuir um novo. Idealmente, esse será um marcador existente que se encaixa na política, mas às vezes um novo rótulo será necessário, e as regras de acesso a ele serão necessários. Adicione seus rótulos aos arquivos de contexto apropriados.
  7. Identifique domínios/processos que devem ter seus próprios domínios de segurança. Você provavelmente precisará escrever uma política completamente nova para cada um. Todos serviços gerados por init, por exemplo, devem ter as por conta própria. Os comandos a seguir ajudam a revelar aqueles que continuam em execução (mas TODOS serviços precisam desse tratamento):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Revise init.device.rc para identificar os domínios que não têm um tipo de domínio. Atribua a eles um domínio no início da sua de desenvolvimento para evitar a adição de regras ao init ou ao confundir os acessos init com os da uma política própria.
  9. Configurar BOARD_CONFIG.mk para usar BOARD_SEPOLICY_* variáveis. Consulte a README em system/sepolicy para mais detalhes sobre a configuração.
  10. Analise os arquivos init.device.rc e fstab.device e garanta que cada uso de mount corresponda a uma um sistema de arquivos rotulado ou que uma opção context= mount especificado.
  11. Passe por cada negação e crie uma política do SELinux para lidar adequadamente com cada uma. Consulte os exemplos em Personalização.

Começar com as políticas no AOSP e depois se basear nelas para suas próprias personalizações. Para mais informações sobre estratégias e analisar algumas dessas etapas, ver Como escrever política do SELinux.

Casos de uso

Aqui estão alguns exemplos específicos de explorações a serem consideradas ao criar o seu próprio e políticas de SELinux associadas:

Links simbólicos - Como os links simbólicos aparecem como arquivos, eles são muitas vezes lidos como arquivos, o que pode levar a exploits. Por exemplo, algumas contas privilegiadas componentes, como init, mudam as permissões de determinados arquivos, muitas vezes fica aberta demais.

Os invasores podem substituir esses arquivos por links simbólicos para o código que controlam, permitindo que o invasor substitua arquivos arbitrários. Mas, se você sabe aplicativo nunca transferirá um link simbólico, você poderá proibi-lo de fazer isso com o SELinux.

Arquivos do sistema: considere a classe de arquivos de sistema que só pode ser modificado pelo servidor do sistema. Ainda assim, desde netd, init e vold são executadas como raiz, podem acessar esses arquivos de sistema. Portanto, se o netd fica comprometido, pode esses arquivos e possivelmente o próprio servidor do sistema.

Com o SELinux, você pode identificar esses arquivos como arquivos de dados do servidor do sistema. Portanto, o único domínio que tem acesso de leitura/gravação a eles é o servidor do sistema. Mesmo que o netd ficasse comprometido, não era possível trocar de domínio para o domínio do servidor do sistema e acessar esses arquivos de sistema, embora seja executado como raiz.

Dados do app: outro exemplo é a classe de funções que precisa ser executado como raiz, mas não deve conseguir acessar os dados do app. Isso é muito úteis, pois podem ser feitas declarações abrangentes, como determinados domínios não relacionados aos dados do aplicativo impedindo o acesso à Internet.

setattr: para comandos como chmod e chown, é possível identificar o conjunto de arquivos em que o domínio pode realizar setattr. Qualquer coisa além disso pode ser proibidas dessas alterações, mesmo pelo acesso raiz. Assim, um aplicativo pode executar chmod e chown em relação aos rotulados app_data_files, mas não shell_data_files ou system_data_files.