Este artigo descreve como o Android lida com os problemas de compatibilidade de políticas com OTAs de plataforma, em que as configurações do SELinux da nova plataforma podem diferir das configurações do SELinux do fornecedor antigo.
O projeto de política SELinux baseado em agudos considera uma distinção binária entre política de plataforma e de fornecedor ; o esquema se torna mais complicado se as partições do fornecedor gerarem dependências, como platform
< vendor
< oem
.
No Android 8.0 e superior, a política global do SELinux é dividida em componentes privados e públicos. Os componentes públicos consistem na política e na infraestrutura associada, que garantem a disponibilidade para uma versão da plataforma. Essa política será exposta aos criadores de políticas do fornecedor para permitir que os fornecedores criem um arquivo de política do fornecedor que, quando combinado com a política fornecida pela plataforma, resulta em uma política totalmente funcional para um dispositivo.
- Para controle de versão, a política pública de plataforma exportada será escrita como atributos .
- Para facilitar a escrita da política, os tipos exportados serão transformados em atributos com versão como parte do processo de criação da política. Os tipos públicos também podem ser usados diretamente nas decisões de rotulagem fornecidas pelos arquivos de contexto do fornecedor.
O Android mantém um mapeamento entre os tipos concretos exportados na política da plataforma e os atributos de versão correspondentes para cada versão da plataforma . Isso garante que, quando os objetos forem rotulados com um tipo, ele não quebre o comportamento garantido pela política pública da plataforma em uma versão anterior. Esse mapeamento é mantido mantendo um arquivo de mapeamento atualizado para cada versão da plataforma , que mantém as informações de associação de atributos para cada tipo exportado na política pública.
Propriedade e rotulagem do objeto
Ao personalizar a política no Android 8.0 e superior, a propriedade deve ser claramente definida para cada objeto para manter a plataforma e a política do fornecedor separadas. Por exemplo, se o fornecedor rotular /dev/foo
e a plataforma rotular /dev/foo
em um OTA subsequente, haverá um comportamento indefinido. Para o SELinux, isso se manifesta como uma colisão de rotulagem. O nó do dispositivo pode ter apenas um único rótulo que resolve o rótulo aplicado por último. Como resultado:
- Os processos que precisam de acesso ao rótulo aplicado sem sucesso perderão o acesso ao recurso.
- Os processos que obtêm acesso ao arquivo podem ser interrompidos porque o nó de dispositivo incorreto foi criado.
As propriedades do sistema também têm potencial para colisões de nomes que podem resultar em comportamento indefinido no sistema (assim como para rotulagem do SELinux). Podem ocorrer colisões entre os rótulos da plataforma e do fornecedor para qualquer objeto que tenha um rótulo SELinux, incluindo propriedades, serviços, processos, arquivos e soquetes. Para evitar esses problemas, defina claramente a propriedade desses objetos.
Além das colisões de rótulos, os nomes de tipo/atributo do SELinux também podem colidir. Uma colisão de tipo/nome de atributo sempre resultará em um erro do compilador de política.
Namespace de tipo/atributo
O SELinux não permite múltiplas declarações do mesmo tipo/atributo. A política com declarações duplicadas não será compilada. Para evitar colisões de tipo e nome de atributo, todas as declarações de fornecedor devem ter namespace começando com np_
.
type foo, domain; → type np_foo, domain;
Propriedade do sistema e propriedade da rotulagem do processo
Evitar colisões de rotulagem é melhor resolvido usando namespaces de propriedade. Para identificar facilmente as propriedades da plataforma e evitar conflitos de nomes ao renomear ou adicionar propriedades de plataforma exportada, certifique-se de que todas as propriedades do fornecedor tenham seus próprios prefixos:
Tipo de Propriedade | Prefixos aceitáveis |
---|---|
propriedades de controle | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor. |
gravável | vendor. |
somente leitura | ro.vendor. ro.boot. ro.hardware. |
persistente | persist.vendor. |
Os fornecedores podem continuar a usar ro.boot.*
(que vem do cmdline do kernel) e ro.hardware.*
(uma propriedade óbvia relacionada ao hardware).
Todos os serviços do fornecedor nos arquivos init rc devem ter o vendor.
para serviços em arquivos init rc de partições que não são do sistema. Regras semelhantes são aplicadas aos rótulos do SELinux para as propriedades do fornecedor ( vendor_
para as propriedades do fornecedor).
Propriedade do arquivo
Prevenir colisões de arquivos é um desafio porque a política de plataforma e de fornecedor geralmente fornece rótulos para todos os sistemas de arquivos. Ao contrário da nomeação de tipos, o namespace de arquivos não é prático, pois muitos deles são criados pelo kernel. Para evitar essas colisões, siga as orientações de nomenclatura para sistemas de arquivos nesta seção. Para o Android 8.0, estas são recomendações sem aplicação técnica. No futuro, essas recomendações serão aplicadas pelo Vendor Test Suite (VTS).
Sistema (/sistema)
Somente a imagem do sistema deve fornecer rótulos para /system
componentes por meio de file_contexts
, service_contexts
, etc. Se rótulos para /system
componentes forem adicionados na política /vendor
, uma atualização OTA somente de estrutura pode não ser possível.
Fornecedor (/fornecedor)
A política AOSP SELinux já rotula partes da partição do vendor
com as quais a plataforma interage, o que permite escrever regras SELinux para que os processos da plataforma possam conversar e/ou acessar partes da partição do vendor
. Exemplos:
/vendor | Rótulo fornecido pela plataforma | Processos da plataforma dependendo do rótulo |
---|---|---|
/vendor(/. * )? | vendor_file | Todos os clientes HAL no framework, ueventd , etc. |
/vendor/framework(/. * )? | vendor_framework_file | dex2oat , appdomain , etc. |
/vendor/app(/. * )? | vendor_app_file | dex2oat , installd , idmap , etc. |
/vendor/overlay(/. * ) | vendor_overlay_file | system_server , zygote , idmap , etc. |
Como resultado, regras específicas devem ser seguidas (impostas por neverallows
) ao rotular arquivos adicionais na partição do vendor
:
-
vendor_file
deve ser o rótulo padrão para todos os arquivos na partição dovendor
. A política da plataforma exige isso para acessar implementações de HAL de passagem. - Todos os novos
exec_types
adicionados na partição dovendor
por meio do fornecedor SEPolicy devem ter o atributovendor_file_type
. Isso é aplicado através de neverallows. - Para evitar conflitos com futuras atualizações de plataforma/framework, evite rotular arquivos que não sejam
exec_types
na partição dovendor
. - Todas as dependências de biblioteca para HALs do mesmo processo identificadas por AOSP devem ser rotuladas como
same_process_hal_file.
Procfs (/proc)
Arquivos em /proc
podem ser rotulados usando apenas o rótulo genfscon
. No Android 7.0, tanto a plataforma quanto a política do fornecedor usavam genfscon
para rotular arquivos em procfs
.
Recomendação: somente rótulos de política de plataforma /proc
. Se os processos do vendor
precisarem de acesso a arquivos em /proc
que estão atualmente rotulados com o rótulo padrão ( proc
), a política do fornecedor não deve rotulá-los explicitamente e deve usar o tipo proc
genérico para adicionar regras para domínios de fornecedor. Isso permite que as atualizações da plataforma acomodem futuras interfaces de kernel expostas por meio de procfs
e as rotulem explicitamente conforme necessário.
Debugfs (/sys/kernel/debug)
Debugfs
pode ser rotulado em file_contexts
e genfscon
. No Android 7.0 ao Android 10, tanto a plataforma quanto o rótulo do fornecedor debugfs
.
No Android 11, debugfs
não pode ser acessado ou montado em dispositivos de produção. Os fabricantes de dispositivos devem remover debugfs
.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
podem ser rotulados em file_contexts
e genfscon
. No Android 7.0, apenas a plataforma rotula tracefs
.
Recomendação: Somente a plataforma pode rotular tracefs
.
Sysfs (/sys)
Arquivos em /sys
podem ser rotulados usando file_contexts
e genfscon
. No Android 7.0, tanto a plataforma quanto o fornecedor usam file_contexts
e genfscon
para rotular arquivos em sysfs
.
Recomendação: A plataforma pode rotular nós sysfs
que não são específicos do dispositivo. Caso contrário, apenas o fornecedor pode rotular os arquivos.
tmpfs (/dev)
Arquivos em /dev
podem ser rotulados em file_contexts
. No Android 7.0, arquivos de etiqueta de plataforma e fornecedor aqui.
Recomendação: O fornecedor pode rotular apenas arquivos em /dev/vendor
(por exemplo, /dev/vendor/foo
, /dev/vendor/socket/bar
).
Raiz (/)
Arquivos em /
podem ser rotulados em file_contexts
. No Android 7.0, arquivos de etiqueta de plataforma e fornecedor aqui.
Recomendação: Somente o sistema pode rotular arquivos em /
.
Dados (/dados)
Os dados são rotulados por meio de uma combinação de file_contexts
e seapp_contexts
.
Recomendação: não permita a rotulagem do fornecedor fora /data/vendor
. Somente a plataforma pode rotular outras partes de /data
.
Atributos de compatibilidade
A política SELinux é uma interação entre os tipos de origem e destino para classes de objetos e permissões específicas. Cada objeto (processos, arquivos, etc.) afetado pela política do SELinux pode ter apenas um tipo, mas esse tipo pode ter vários atributos.
A política é escrita principalmente em termos de tipos existentes:
allow source_type target_type:target_class permission(s);
Isso funciona porque a política foi escrita com conhecimento de todos os tipos. No entanto, se a política do fornecedor e a política da plataforma usarem tipos específicos e o rótulo de um objeto específico mudar em apenas uma dessas políticas, a outra poderá conter a política que ganhou ou perdeu acesso anteriormente confiado. Por exemplo:
File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;
Pode ser alterado para:
File_contexts: /sys/A u:object_r:sysfs_A:s0
Embora a política do fornecedor permanecesse a mesma, o v_domain
perderia acesso devido à falta de política para o novo tipo sysfs_A
.
Ao definir uma política em termos de atributos, podemos dar ao objeto subjacente um tipo que tenha um atributo correspondente à política tanto para a plataforma quanto para o código do fornecedor. Isso pode ser feito para todos os tipos para criar efetivamente uma política de atributos em que os tipos concretos nunca são usados. Na prática, isso é necessário apenas para as partes da política que se sobrepõem entre plataforma e fornecedor, que são definidas e fornecidas como política pública de plataforma que é criada como parte da política do fornecedor.
Definir a política pública como atributos com versão atende a duas metas de compatibilidade de política:
- Certifique-se de que o código do fornecedor continue funcionando após a atualização da plataforma . Obtido pela adição de atributos a tipos concretos para objetos correspondentes àqueles nos quais o código do fornecedor dependia, preservando o acesso.
- Capacidade de descontinuar a política . Obtido ao delinear claramente os conjuntos de políticas em atributos que podem ser removidos assim que a versão à qual eles correspondem não for mais suportada. O desenvolvimento pode continuar na plataforma, sabendo que a política antiga ainda está presente na política do fornecedor e será removida automaticamente quando/se for atualizada.
Capacidade de escrita da política
Para atingir o objetivo de não exigir conhecimento de alterações de versão específicas para o desenvolvimento de políticas, o Android 8.0 inclui um mapeamento entre os tipos de política pública de plataforma e seus atributos. O tipo foo
é mapeado para o atributo foo_v N
, em que N
é a versão de destino. vN
corresponde à variável de construção PLATFORM_SEPOLICY_VERSION
e tem o formato MM.NN
, em que MM
corresponde ao número do SDK da plataforma e NN
é uma versão específica da sepolicy da plataforma.
Os atributos na política pública não são versionados, mas existem como uma API na qual a plataforma e a política do fornecedor podem ser construídas para manter a interface entre as duas partições estável. Tanto os redatores de políticas da plataforma quanto do fornecedor podem continuar a escrever as políticas como estão escritas hoje.
Política pública de plataforma exportada como allow source_foo target_bar: class perm ;
está incluído como parte da política do fornecedor. Durante a compilação (que inclui a versão correspondente) ela é transformada na política que irá para a parte do fornecedor do dispositivo (mostrada na Common Intermediate Language (CIL) transformada):
(allow source_foo_vN target_bar_vN (class (perm)))
Como a política do fornecedor nunca está à frente da plataforma, ela não deve se preocupar com versões anteriores. No entanto, a política da plataforma precisará saber até onde está a política do fornecedor, incluir atributos para seus tipos e definir a política correspondente aos atributos com versão.
Diferenças de política
A criação automática de atributos adicionando _v N
ao final de cada tipo não faz nada sem o mapeamento de atributos para tipos em diferenças de versão. O Android mantém um mapeamento entre versões para atributos e um mapeamento de tipos para esses atributos. Isso é feito nos arquivos de mapeamento mencionados acima com instruções, como (CIL):
(typeattributeset foo_vN (foo))
Atualizações da plataforma
A seção a seguir detalha os cenários para atualizações de plataforma.
Mesmos tipos
Esse cenário ocorre quando um objeto não altera os rótulos nas versões de política. Isso é o mesmo para os tipos de origem e destino e pode ser visto com /dev/binder
, rotulado como binder_device
em todas as versões. É representado na política transformada como:
binder_device_v1 … binder_device_vN
Ao atualizar de v1
→ v2
, a política da plataforma deve conter:
type binder_device; -> (type binder_device) (in CIL)
No arquivo de mapeamento v1 (CIL):
(typeattributeset binder_device_v1 (binder_device))
No arquivo de mapeamento v2 (CIL):
(typeattributeset binder_device_v2 (binder_device))
Na política de fornecedor v1 (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
Na política de fornecedor v2 (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
Novos tipos
Esse cenário ocorre quando a plataforma adiciona um novo tipo, o que pode acontecer ao adicionar novos recursos ou durante o fortalecimento da política.
- Novo recurso . Quando o tipo está rotulando um objeto que não existia anteriormente (como um novo processo de serviço), o código do fornecedor não interagiu diretamente com ele anteriormente, portanto, não existe uma política correspondente. O novo atributo correspondente ao tipo não possui um atributo na versão anterior e, portanto, não precisaria de uma entrada no arquivo de mapeamento destinado a essa versão.
- Endurecimento da política . Quando o tipo representa proteção de política, o novo atributo de tipo deve se vincular novamente a uma cadeia de atributos correspondente ao anterior (semelhante ao exemplo anterior, alterando
/sys/A
desysfs
parasysfs_A
). O código do fornecedor depende de uma regra que permite o acesso asysfs
e precisa incluir essa regra como um atributo do novo tipo.
Ao atualizar de v1
→ v2
, a política da plataforma deve conter:
type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)
No arquivo de mapeamento v1 (CIL):
(typeattributeset sysfs_v1 (sysfs sysfs_A))
No arquivo de mapeamento v2 (CIL):
(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))
Na política de fornecedor v1 (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Na política de fornecedor v2 (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
Tipos removidos
Esse cenário (raro) ocorre quando um tipo é removido, o que pode acontecer quando o objeto subjacente:
- Permanece, mas recebe um rótulo diferente.
- É removido pela plataforma.
Durante o afrouxamento da política, um tipo é removido e o objeto rotulado com esse tipo recebe um rótulo diferente já existente. Isso representa uma fusão de mapeamentos de atributos: o código do fornecedor ainda deve poder acessar o objeto subjacente pelo atributo que costumava possuir, mas o restante do sistema deve agora poder acessá-lo com seu novo atributo.
Se o atributo para o qual foi trocado for novo, então a reetiquetagem é a mesma que no caso do novo tipo, exceto que quando um rótulo existente é usado, a adição do atributo antigo novo tipo faria com que outros objetos também rotulados com este tipo para ser recém-acessível. Isso é essencialmente o que é feito pela plataforma e é considerado uma compensação aceitável para manter a compatibilidade.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Exemplo de versão 1: recolhimento de tipos (remoção de sysfs_A)
Ao atualizar de v1
→ v2
, a política da plataforma deve conter:
type sysfs; (type sysfs) (in CIL)
No arquivo de mapeamento v1 (CIL):
(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))
No arquivo de mapeamento v2 (CIL):
(typeattributeset sysfs_v2 (sysfs))
Na política de fornecedor v1 (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
Na política de fornecedor v2 (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
Exemplo de versão 2: removendo completamente (tipo foo)
Ao atualizar de v1
→ v2
, a política da plataforma deve conter:
# nothing - we got rid of the type
No arquivo de mapeamento v1 (CIL):
(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))
No arquivo de mapeamento v2 (CIL):
# nothing - get rid of it
Na política de fornecedor v1 (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
Na política de fornecedor v2 (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
Nova classe/permissões
Esse cenário ocorre quando uma atualização de plataforma introduz novos componentes de política que não existem nas versões anteriores. Por exemplo, quando o Android adicionou o gerenciador de objetos servicemanager
que criou as permissões add, find e list, os daemons do fornecedor que desejavam se registrar no servicemanager
precisavam de permissões que não estavam disponíveis. No Android 8.0, apenas a política da plataforma pode adicionar novas classes e permissões.
Para permitir que todos os domínios que possam ter sido criados ou estendidos pela política do fornecedor usem a nova classe sem obstrução, a política da plataforma precisa incluir uma regra semelhante a:
allow {domain -coredomain} *:new_class perm;
Isso pode até exigir uma política que permita o acesso a todos os tipos de interface (política pública), para garantir que a imagem do fornecedor tenha acesso. Se isso resultar em uma política de segurança inaceitável (como pode acontecer com as alterações do servicemanager), uma atualização do fornecedor pode ser forçada.
Classe/permissões removidas
Esse cenário ocorre quando um gerenciador de objetos é removido (como o gerenciador de objetos ZygoteConnection
) e não deve causar problemas. A classe e as permissões do gerenciador de objetos podem permanecer definidas na política até que a versão do fornecedor não a utilize mais. Isso é feito adicionando as definições ao arquivo de mapeamento correspondente.
Personalização do fornecedor para tipos novos/remarcados
Novos tipos de fornecedores estão no centro do desenvolvimento de políticas de fornecedores, pois são necessários para descrever novos processos, binários, dispositivos, subsistemas e dados armazenados. Como tal, é imperativo permitir a criação de tipos definidos pelo fornecedor.
Como a política do fornecedor é sempre a mais antiga no dispositivo, não há necessidade de converter automaticamente todos os tipos de fornecedores em atributos na política. A plataforma não depende de nada rotulado na política do fornecedor porque a plataforma não tem conhecimento disso; no entanto, a plataforma fornecerá os atributos e tipos públicos que usa para interagir com objetos rotulados com esses tipos (como domain
, sysfs_type
, etc.). Para que a plataforma continue a interagir corretamente com esses objetos, os atributos e tipos devem ser aplicados adequadamente e regras específicas podem precisar ser adicionadas aos domínios personalizáveis (como init
).
Alterações de atributo para Android 9
Os dispositivos atualizados para o Android 9 podem usar os atributos a seguir, mas os dispositivos iniciados com o Android 9 não devem.
Atributos do infrator
O Android 9 inclui estes atributos relacionados ao domínio:
-
data_between_core_and_vendor_violators
. Atributo para todos os domínios que violam o requisito de não compartilhar arquivos por caminho entre ovendor
ecoredomains
. Os processos da plataforma e do fornecedor não devem usar arquivos em disco para se comunicar (ABI instável). Recomendação:- O código do fornecedor deve usar
/data/vendor
. - O sistema não deve usar
/data/vendor
.
- O código do fornecedor deve usar
-
system_executes_vendor_violators
. Atributo para todos os domínios do sistema (exceto domíniosinit
eshell domains
) que violam o requisito de não executar binários do fornecedor. A execução dos binários do fornecedor tem uma API instável. A plataforma não deve executar binários de fornecedores diretamente. Recomendação:- Essas dependências de plataforma em binários de fornecedores devem estar por trás de HIDL HALs.
OU
-
coredomains
que precisam de acesso aos binários do fornecedor devem ser movidos para a partição do fornecedor e, assim, deixar de sercoredomain
.
- Essas dependências de plataforma em binários de fornecedores devem estar por trás de HIDL HALs.
Atributos não confiáveis
Aplicativos não confiáveis que hospedam código arbitrário não devem ter acesso aos serviços HwBinder, exceto aqueles considerados suficientemente seguros para acesso de tais aplicativos (veja serviços seguros abaixo). As duas principais razões para isso são:
- Servidores HwBinder não executam autenticação de cliente porque HIDL atualmente não expõe informações de UID do chamador. Mesmo que o HIDL tenha exposto esses dados, muitos serviços HwBinder operam em um nível inferior ao dos aplicativos (como HALs) ou não devem depender da identidade do aplicativo para autorização. Assim, por segurança, a suposição padrão é que todo serviço HwBinder trate todos os seus clientes como igualmente autorizados a realizar as operações oferecidas pelo serviço.
- Os servidores HAL (um subconjunto de serviços HwBinder) contêm código com maior taxa de incidência de problemas de segurança do que os componentes do
system/core
e têm acesso às camadas inferiores da pilha (até o hardware), aumentando assim as oportunidades de contornar o modelo de segurança do Android .
Serviços seguros
Os serviços seguros incluem:
-
same_process_hwservice
. Esses serviços (por definição) são executados no processo do cliente e, portanto, têm o mesmo acesso que o domínio do cliente no qual o processo é executado. -
coredomain_hwservice
. Esses serviços não apresentam riscos associados ao motivo nº 2. -
hal_configstore_ISurfaceFlingerConfigs
. Este serviço foi projetado especificamente para uso por qualquer domínio. -
hal_graphics_allocator_hwservice
. Essas operações também são oferecidas pelo serviçosurfaceflinger
Binder, que os aplicativos têm permissão para acessar. -
hal_omx_hwservice
. Esta é uma versão HwBinder do serviçomediacodec
Binder, que os aplicativos têm permissão para acessar. -
hal_codec2_hwservice
. Esta é uma versão mais recente dohal_omx_hwservice
.
Atributos utilizáveis
Todos os hwservices
não considerados seguros possuem o atributo untrusted_app_visible_hwservice
. Os servidores HAL correspondentes possuem o atributo untrusted_app_visible_halserver
. Dispositivos iniciados com Android 9 NÃO DEVEM usar nenhum atributo untrusted
.
Recomendação:
- Aplicativos não confiáveis devem falar com um serviço de sistema que fale com o fornecedor HIDL HAL. Por exemplo, os aplicativos podem conversar com
binderservicedomain
, entãomediaserver
(que é umbinderservicedomain
) por sua vez fala com ohal_graphics_allocator
.OU
- Os aplicativos que precisam de acesso direto às HALs do
vendor
devem ter seu próprio domínio de política de segurança definido pelo fornecedor.
Testes de atributo de arquivo
O Android 9 inclui testes de tempo de compilação que garantem que todos os arquivos em locais específicos tenham os atributos apropriados (como, todos os arquivos em sysfs
têm o atributo sysfs_type
necessário).
Política pública de plataforma
A política pública de plataforma é o núcleo da conformidade com o modelo de arquitetura do Android 8.0 sem simplesmente manter a união das políticas de plataforma da v1 e v2. Os fornecedores são expostos a um subconjunto de política de plataforma que contém tipos e atributos utilizáveis e regras sobre esses tipos e atributos que se tornam parte da política de fornecedor (ou seja, vendor_sepolicy.cil
).
Tipos e regras são traduzidos automaticamente na política gerada pelo fornecedor em attribute_v N
de forma que todos os tipos fornecidos pela plataforma sejam atributos com versão (no entanto, os atributos não são com versão). A plataforma é responsável por mapear os tipos concretos que fornece nos atributos apropriados para garantir que a política do fornecedor continue funcionando e que as regras fornecidas para uma determinada versão sejam incluídas. A combinação de política pública de plataforma e política de fornecedor atende ao objetivo do modelo de arquitetura do Android 8.0 de permitir compilações independentes de plataforma e fornecedor.
Mapeamento para cadeias de atributos
Ao usar atributos para mapear para versões de política, um tipo mapeia para um atributo ou vários atributos, garantindo que os objetos rotulados com o tipo sejam acessíveis por meio de atributos correspondentes aos seus tipos anteriores.
Manter uma meta de ocultar informações de versão do escritor de política significa gerar automaticamente os atributos com versão e atribuí-los aos tipos apropriados. No caso comum de tipos estáticos, isso é direto: type_foo
mapeia para type_foo_v1
.
Para uma alteração de rótulo de objeto como sysfs
→ sysfs_A
ou mediaserver
→ audioserver
, criar esse mapeamento não é trivial (e é descrito nos exemplos acima). Os mantenedores da política da plataforma devem determinar como criar o mapeamento em pontos de transição para objetos, o que requer entender o relacionamento entre objetos e seus rótulos atribuídos e determinar quando isso ocorre. Para compatibilidade com versões anteriores, essa complexidade precisa ser gerenciada no lado da plataforma, que é a única partição que pode aumentar.
Atualizações de versão
Para simplificar, a plataforma Android libera uma versão de sepolicy quando uma nova ramificação de lançamento é cortada. Conforme descrito acima, o número da versão está contido em PLATFORM_SEPOLICY_VERSION
e tem o formato MM.nn
, em que MM
corresponde ao valor do SDK e nn
é um valor privado mantido em /platform/system/sepolicy.
Por exemplo, 19.0
para Kitkat, 21.0
para Lollipop, 22.0
para Lollipop-MR1 23.0
para Marshmallow, 24.0
para Nougat, 25.0
para Nougat-MR1, 26.0
para Oreo, 27.0
para Oreo-MR1 e 28.0
para Android 9. Uprevs não são sempre números inteiros. Por exemplo, se um aumento de MR para uma versão exigir uma alteração incompatível em system/sepolicy/public
, mas não um aumento de API, essa versão de sepolicy poderá ser: vN.1
. A versão presente em uma ramificação de desenvolvimento é uma 10000.0
nunca usada em dispositivos de envio.
O Android pode descontinuar a versão mais antiga ao atualizar. Para saber quando suspender o uso de uma versão, o Android pode coletar o número de dispositivos com políticas do fornecedor que executam essa versão do Android e ainda recebem as principais atualizações da plataforma. Se o número for menor que um determinado limite, essa versão será preterida.
Impacto no desempenho de vários atributos
Conforme descrito em https://github.com/SELinuxProject/cil/issues/9 , um grande número de atributos atribuídos a um tipo resulta em problemas de desempenho no caso de uma falha de cache de política.
Como isso foi confirmado como um problema no Android, foram feitas alterações no Android 8.0 para remover atributos adicionados à política pelo compilador de políticas, bem como para remover atributos não utilizados. Essas alterações resolveram regressões de desempenho.
Política pública do System_ext e do produto
A partir do Android 11, as partições system_ext e product podem exportar seus tipos públicos designados para a partição do fornecedor. Como a política pública de plataforma, o fornecedor usa tipos e regras automaticamente traduzidos nos atributos versionados, por exemplo, de type
em type_ N
, onde N
é a versão da plataforma na qual a partição do fornecedor é construída.
Quando as partições system_ext e product são baseadas na mesma versão de plataforma N
, o sistema de compilação gera arquivos de mapeamento base para system_ext/etc/selinux/mapping/ N .cil
e product/etc/selinux/mapping/ N .cil
, que contêm identidade mapeamentos de type
para type_ N
. O fornecedor pode acessar type
com o atributo versionado type_ N
.
Caso apenas as partições system_ext e product sejam atualizadas, digamos N
para N+1
(ou posterior), enquanto o fornecedor permanece em N
, o fornecedor pode perder o acesso aos tipos de partições system_ext e product. Para evitar quebras, as partições system_ext e product devem fornecer arquivos de mapeamento de tipos concretos em atributos type_ N
. Cada parceiro é responsável por manter os arquivos de mapeamento, se eles forem oferecer suporte a N
fornecedores com N+1
(ou posterior) system_ext e partições de produto.
Para isso, espera-se que os parceiros:
- Copie os arquivos de mapeamento de base gerados de
N
system_ext e partições do produto para sua árvore de origem. - Altere os arquivos de mapeamento conforme necessário.
- Instale os arquivos de mapeamento em partições do system_ext e do produto
N+1
(ou posterior).
Por exemplo, suponha que N
system_ext tenha um tipo público chamado foo_type
. Então system_ext/etc/selinux/mapping/ N .cil
na partição N
system_ext ficará assim:
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
Se bar_type
for adicionado a N+1
system_ext, e se bar_type
deve ser mapeado para foo_type
para N
fornecedor, N .cil
pode ser atualizado de
(typeattributeset foo_type_N (foo_type))
para
(typeattributeset foo_type_N (foo_type bar_type))
e então instalado na partição de N+1
system_ext. N
fornecedor pode continuar acessando foo_type
e bar_type de N+1
bar_type
.
Rotulagem de contextos SELinux
Para suportar a distinção entre sepolicy de plataforma e fornecedor, o sistema cria arquivos de contexto SELinux de forma diferente para mantê-los separados.
Contextos de arquivo
O Android 8.0 introduziu as seguintes alterações para file_contexts
:
- Para evitar sobrecarga de compilação adicional no dispositivo durante a inicialização,
file_contexts
deixa de existir no formato binário. Em vez disso, eles são arquivos de texto de expressão regular legíveis, como{property, service}_contexts
(como eram pré-7.0). - Os
file_contexts
são divididos entre dois arquivos:-
plat_file_contexts
- plataforma Android
file_context
que não possui rótulos específicos do dispositivo, exceto para rotular partes da partição/vendor
que devem ser rotuladas com precisão para garantir o funcionamento adequado dos arquivos de sepolicy. - Deve residir na partição do
system
em/system/etc/selinux/plat_file_contexts
no dispositivo e ser carregado porinit
no início junto com ofile_context
do fornecedor.
- plataforma Android
-
vendor_file_contexts
-
file_context
específico do dispositivo construído combinandofile_contexts
encontrados nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve ser instalado em
/vendor/etc/selinux/vendor_file_contexts
na partição dovendor
e ser carregado peloinit
no início junto com a plataformafile_context
.
-
-
Contextos de propriedade
No Android 8.0, o property_contexts
é dividido entre dois arquivos:
-
plat_property_contexts
-
property_context
da plataforma Android que não tem rótulos específicos do dispositivo. - Deve residir na partição do
system
em/system/etc/selinux/plat_property_contexts
e ser carregado porinit
no início junto com o fornecedorproperty_contexts
.
-
-
vendor_property_contexts
-
property_contexts
property_context
nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve residir na partição do
vendor
em/vendor/etc/selinux/vendor_property_contexts
e ser carregado peloinit
no início junto com oproperty_context
da plataforma
-
Contextos de serviço
No Android 8.0, o service_contexts
é dividido entre os seguintes arquivos:
-
plat_service_contexts
-
service_context
específico da plataforma Android para oservicemanager
. Oservice_context
não tem rótulos específicos do dispositivo. - Deve residir na partição do
system
em/system/etc/selinux/plat_service_contexts
e ser carregado peloservicemanager
no início junto com o fornecedorservice_contexts
.
-
-
vendor_service_contexts
-
service_context
específico do dispositivo construído combinandoservice_contexts
encontrados nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve residir na partição do
vendor
em/vendor/etc/selinux/vendor_service_contexts
e ser carregado peloservicemanager
no início junto com a plataformaservice_contexts
. - Embora o
servicemanager
procure por esse arquivo no momento da inicialização, para um dispositivoTREBLE
totalmente compatível, ovendor_service_contexts
NÃO DEVE existir. Isso ocorre porque toda interação entre ovendor
e os processossystem
DEVE passar porhwservicemanager
/hwbinder
.
-
-
plat_hwservice_contexts
- Plataforma Android
hwservice_context
parahwservicemanager
que não possui rótulos específicos do dispositivo. - Deve residir na partição do
system
em/system/etc/selinux/plat_hwservice_contexts
e ser carregado pelohwservicemanager
no início junto com ovendor_hwservice_contexts
.
- Plataforma Android
-
vendor_hwservice_contexts
- O
hwservice_context
específico do dispositivo construído combinandohwservice_contexts
encontrados nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve residir na partição do
vendor
em/vendor/etc/selinux/vendor_hwservice_contexts
e ser carregado pelohwservicemanager
no início junto com oplat_service_contexts
.
- O
-
vndservice_contexts
-
service_context
específico do dispositivo para ovndservicemanager
construído combinandovndservice_contexts
encontrados nos diretórios apontados porBOARD_SEPOLICY_DIRS
noBoardconfig.mk
do dispositivo. - Este arquivo deve residir na partição do
vendor
em/vendor/etc/selinux/vndservice_contexts
e ser carregado pelovndservicemanager
no início.
-
Contextos do Seapp
No Android 8.0, o seapp_contexts
é dividido entre dois arquivos:
-
plat_seapp_contexts
- Plataforma Android
seapp_context
que não possui alterações específicas do dispositivo. - Deve residir na partição do
system
em/system/etc/selinux/plat_seapp_contexts.
- Plataforma Android
-
vendor_seapp_contexts
- Extensão específica do dispositivo para a plataforma
seapp_context
construída combinandoseapp_contexts
encontrados nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve residir na partição do
vendor
em/vendor/etc/selinux/vendor_seapp_contexts
.
- Extensão específica do dispositivo para a plataforma
Permissões MAC
No Android 8.0, o mac_permissions.xml
é dividido entre dois arquivos:
- Plataforma
mac_permissions.xml
- Plataforma Android
mac_permissions.xml
que não tem alterações específicas do dispositivo. - Deve residir na partição do
system
em/system/etc/selinux/.
- Plataforma Android
-
mac_permissions.xml
sem plataforma- Extensão específica do dispositivo para a plataforma
mac_permissions.xml
construída a partir demac_permissions.xml
encontrada nos diretórios apontados porBOARD_SEPOLICY_DIRS
nos arquivosBoardconfig.mk
do dispositivo. - Deve residir na partição do
vendor
em/vendor/etc/selinux/.
- Extensão específica do dispositivo para a plataforma