Inicialização do fornecedor

O processo init tem permissões quase irrestritas e usa scripts de entrada das partições do sistema e do fornecedor para inicializar o sistema durante o processo de inicialização. Esse acesso causa um enorme buraco na divisão sistema/fornecedor da Treble, pois os scripts do fornecedor podem instruir o init a acessar arquivos, propriedades etc. que não fazem parte da interface binária de aplicativo (ABI) estável do fornecedor do sistema.

O fornecedor init foi projetado para fechar essa lacuna usando um domínio separado do Linux com segurança aprimorada (SELinux) vendor_init para executar comandos encontrados em /vendor com permissões específicas do fornecedor.

Mecanismo

O init do fornecedor bifurca um subprocesso do init no início do processo de inicialização com o contexto do SELinux u:r:vendor_init:s0 . Este contexto SELinux tem consideravelmente menos permissões do que o contexto init padrão e seu acesso é limitado a arquivos, propriedades, etc. que são específicos do fornecedor ou parte da ABI estável do fornecedor do sistema.

O Init verifica cada script que carrega para ver se seu caminho começa com /vendor e, em caso afirmativo, marca-o com uma indicação de que seus comandos devem ser executados no contexto init do fornecedor. Cada init embutido é anotado com um booleano que especifica se o comando deve ou não ser executado no subprocesso init do fornecedor:

  • A maioria dos comandos que acessam o sistema de arquivos são anotados para serem executados no subprocesso init do fornecedor e, portanto, estão sujeitos à SEPolicy init do fornecedor.
  • A maioria dos comandos que afetam o estado de inicialização interno (por exemplo, iniciar e interromper serviços) são executados dentro do processo de inicialização normal. Esses comandos são informados de que um script de fornecedor os está chamando para fazer seu próprio tratamento de permissões não SELinux.

O loop de processamento principal do init contém uma verificação de que, se um comando for anotado para ser executado no subprocesso do fornecedor e se originar de um script do fornecedor, esse comando será enviado via comunicação entre processos (IPC) para o subprocesso init do fornecedor, que executa o comando e envia o resultado de volta para init.

Usando a inicialização do fornecedor

O init do fornecedor é habilitado por padrão e suas restrições se aplicam a todos os scripts init presentes na partição /vendor . O init do fornecedor deve ser transparente para os fornecedores cujos scripts já não estão acessando arquivos, propriedades etc. somente do sistema.

No entanto, se os comandos em um determinado script de fornecedor violarem as restrições init do fornecedor, os comandos falharão. Os comandos com falha têm uma linha no log do kernel (visível com dmesg) do init indicando falha. Uma auditoria do SELinux acompanha qualquer comando com falha devido à política do SELinux. Exemplo de uma falha incluindo uma auditoria do SELinux:

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

Se um comando falhar, há duas opções:

  • Se o comando estiver falhando devido a uma restrição intencional (como se o comando estivesse acessando um arquivo ou propriedade do sistema), o comando deve ser reimplementado de maneira amigável ao Treble, passando apenas por interfaces estáveis. As regras Neverallow impedem a adição de permissões para acessar arquivos do sistema que não fazem parte da ABI estável do fornecedor do sistema.
  • Se o rótulo SELinux for novo e ainda não tiver permissões concedidas no sistema vendor_init.te nem permissões excluídas por meio das regras neverallow, o novo rótulo poderá receber permissões no vendor_init.te específico do dispositivo.

Para dispositivos lançados antes do Android 9, as regras neverallows podem ser ignoradas adicionando o atributo type data_between_core_and_vendor_violators ao arquivo vendor_init.te específico do dispositivo.

Localizações do código

A maior parte da lógica para o fornecedor init IPC está em system/core/init/subcontext.cpp .

A tabela de comandos está na classe BuiltinFunctionMap em system/core/init/builtins.cpp e inclui anotações que indicam se o comando deve ser executado no subprocesso init do fornecedor.

A SEPolicy para vendor init é dividida nos diretórios private ( system/sepolicy/private/vendor_init.te ) e public ( system/sepolicy/public/vendor_init.te ) em system/sepolicy.