Vendor init

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 uma grande falha na divisão sistema/fornecedor do Treble, já que scripts do fornecedor podem instruir a inicialização a acessar arquivos, propriedades etc. que não fazem parte da interface binária de aplicativo (ABI) estável do sistema-fornecedor.

O init do fornecedor foi projetado para resolver esse problema 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 cria um subprocesso de init no início do processo de inicialização com o contexto do SELinux u:r:vendor_init:s0. Esse contexto do SELinux tem muito menos permissões do que o contexto init padrão, e o acesso dele é restrito a arquivos, propriedades etc. específicos do fornecedor ou parte da ABI estável do sistema-fornecedor.

O init verifica cada script carregado para ver se o caminho começa com /vendor e, em caso afirmativo, marca com uma indicação de que os comandos precisam ser executados no contexto de inicialização do fornecedor. Cada built-in de inicialização é anotado com um booleano que especifica se o comando precisa ser executado no subprocesso de inicialização do fornecedor:

  • A maioria dos comandos que acessam o sistema de arquivos é anotada para ser executada no subprocesso de inicialização do fornecedor e, portanto, está sujeita à SEPolicy de inicialização do fornecedor.
  • A maioria dos comandos que afetam o estado de inicialização interna (por exemplo, iniciar e parar serviços) é executada no processo normal de inicialização. Esses comandos são informados de que um script do fornecedor está chamando-os para fazer o próprio processamento de permissões não SELinux.

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

Usar vendor init

A inicialização do fornecedor é ativada por padrão, e as restrições dela se aplicam a todos os scripts de inicialização presentes na partição /vendor. A inicialização do fornecedor deve ser transparente para fornecedores cujos scripts já não acessam arquivos, propriedades etc. somente do sistema.

No entanto, se os comandos em um determinado script do fornecedor violarem as restrições de inicialização do fornecedor, eles vão falhar. Os comandos com falha têm uma linha no registro do kernel (visível com dmesg) do init indicando a falha. Uma auditoria do SELinux acompanha qualquer comando com falha devido à política do SELinux. Exemplo de uma falha que inclui 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, você terá duas opções:

  • Se o comando falhar devido a uma restrição intencional (por exemplo, se o comando estiver acessando um arquivo ou uma propriedade do sistema), ele precisará ser reimplementado de uma maneira compatível com o 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 sistema-fornecedor.
  • Se o rótulo do SELinux for novo e ainda não tiver permissões concedidas no sistema vendor_init.te nem permissões excluídas pelas 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 "neverallow" podem ser ignoradas adicionando o atributo de tipo data_between_core_and_vendor_violators ao arquivo vendor_init.te específico do dispositivo.

Locais 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 precisa ser executado no subprocesso de inicialização do fornecedor.

A SEPolicy para init do fornecedor é dividida entre os diretórios privado (system/sepolicy/private/vendor_init.te) e público (system/sepolicy/public/vendor_init.te) em system/sepolicy.