Inicialização do fornecedor

O processo de inicialização 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 grande buraco na divisão Treble sistema/fornecedor, pois os scripts dos fornecedores podem instruir o init a acessar arquivos, propriedades, etc. que não fazem parte da interface binária de aplicativo (ABI) sistema-fornecedor estável.

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

Mecanismo

O init do fornecedor bifurca um subprocesso de init no início do processo de inicialização com o contexto 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 de 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 de inicialização do fornecedor e, portanto, estão sujeitos à SEPolicy de inicialização do fornecedor.
  • A maioria dos comandos que afetam o estado de inicialização interno (por exemplo, iniciar e parar serviços) são executados dentro do processo normal de inicialização. 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 de inicialização presentes na partição /vendor . O init do fornecedor deve ser transparente para fornecedores cujos scripts já não estão acessando apenas arquivos, propriedades, etc.

No entanto, se os comandos em um determinado script de fornecedor violarem as restrições de inicialização do fornecedor, os comandos falharão. 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 que falhou devido à política do SELinux. Exemplo de uma falha incluindo uma auditoria 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 pretendida (como se o comando estiver 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 tipo data_between_core_and_vendor_violators ao arquivo vendor_init.te específico do dispositivo.

Localizações de código

A maior parte da lógica para o IPC de inicialização do fornecedor 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 init do fornecedor é dividida nos diretórios privado (system/sepolicy/private/vendor_init.te ) e público ( system/sepolicy/public/vendor_init.te ) em system/sepolicy.