Nesta página, descrevemos como o Android lida com os problemas de compatibilidade de políticas com atualizações OTA (pela rede) da plataforma, em que as novas configurações do SELinux da plataforma podem ser diferentes das configurações antigas do SELinux do fornecedor.
Propriedade e rotulagem de objetos
A propriedade precisa ser claramente definida para cada objeto, mantendo separadas as políticas da plataforma e do fornecedor. Por exemplo, se a política do fornecedor rotular /dev/foo e a política da plataforma rotular /dev/foo em uma OTA subsequente, haverá um comportamento indefinido, como uma negação inesperada ou, mais gravemente, uma falha de inicialização. Para o SELinux, isso se manifesta como uma colisão de rotulagem. O nó do dispositivo
pode ter apenas um rótulo que é resolvido para o último rótulo aplicado.
Como resultado:
- Os processos que precisam de acesso ao rótulo que não foi aplicado perdem o acesso ao recurso.
- Os processos que ganham acesso ao arquivo podem falhar porque o nó de dispositivo errado foi criado.
Colisões entre rótulos de plataforma e fornecedor podem ocorrer em qualquer objeto que tenha um rótulo do SELinux, incluindo propriedades, serviços, processos, arquivos e sockets. Para evitar esses problemas, defina claramente a propriedade desses objetos.
Namespaces de tipo/atributo
Além de colisões de rótulos, os nomes de tipos e atributos do SELinux também podem entrar em conflito. O SELinux não permite várias declarações dos mesmos tipos e atributos. Uma política com declarações duplicadas não é compilada. Para evitar colisões de tipo e nome de atributo, é altamente recomendável que todas as declarações de fornecedor comecem com o prefixo vendor_. Por exemplo, os fornecedores precisam usar
type vendor_foo, domain; em vez de type foo, domain;.
Propriedade do arquivo
Evitar colisões para arquivos é um desafio porque a política da plataforma e do fornecedor geralmente fornece rótulos para todos os sistemas de arquivos. Ao contrário da nomenclatura de tipos, o namespace de arquivos não é prático, já que 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. No Android 8.0, essas são recomendações sem aplicação técnica. No futuro, essas recomendações serão aplicadas pelo Vendor Test Suite (VTS).
Sistema (/system)
Somente a imagem do sistema precisa fornecer rótulos para componentes /system
por meio de file_contexts, service_contexts etc. Se rótulos
para componentes /system forem adicionados à política do fornecedor, uma
atualização OTA somente de framework talvez não seja possível.
Fornecedor (/vendor)
A política do SELinux do AOSP já rotula partes da partição vendor
com que a plataforma interage, o que permite escrever regras do SELinux para que os
processos da plataforma possam se comunicar ou acessar partes da partição vendor
(link em inglês). Exemplos:
| /vendor path | Rótulo fornecido pela plataforma | Processos da plataforma dependendo do rótulo |
|---|---|---|
/vendor(/.*)?
|
vendor_file
|
Todos os clientes HAL na estrutura, 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 precisam ser seguidas (aplicadas por neverallows) ao rotular arquivos adicionais na partição vendor:
vendor_fileprecisa ser o marcador padrão de todos os arquivos na partiçãovendor. A política da plataforma exige isso para acessar implementações de HAL de transferência direta.- Todos os novos
exec_typesadicionados na partiçãovendorpela política do fornecedor precisam ter o atributovendor_file_type. Isso é imposto por "neverallows". - Para evitar conflitos com futuras atualizações de plataforma/framework, não rotule arquivos diferentes de
exec_typesna partiçãovendor. - Todas as dependências de biblioteca para HALs de mesmo processo identificados pelo AOSP precisam ser
rotuladas como
same_process_hal_file..
Procfs (/proc)
Os arquivos em /proc podem ser rotulados usando apenas o rótulo genfscon. No Android 7.0, as políticas de plataforma e fornecedor usavam genfscon para rotular arquivos em procfs.
Recomendação:use apenas rótulos de políticas da plataforma /proc.
Se os processos do fornecedor precisarem de acesso a arquivos em /proc que estão
rotulados com o rótulo padrão (proc), a política do fornecedor
não deve rotulá-los explicitamente. Em vez disso, use o tipo genérico
proc para adicionar regras aos domínios do fornecedor. Isso permite que as atualizações da plataforma acomodem futuras interfaces do kernel expostas pelo 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, a plataforma e o rótulo do fornecedor
debugfs.
No Android 11, debugfs não pode ser
acessado ou ativado em dispositivos de produção. Os fabricantes de dispositivos precisam
remover debugfs.
Tracefs (/sys/kernel/debug/tracing)
Tracefs pode ser rotulado em file_contexts e
genfscon. No Android 7.0, apenas os rótulos da plataforma
tracefs.
Recomendação:somente a plataforma pode rotular tracefs.
Sysfs (/sys)
Os arquivos em /sys podem ser rotulados usando file_contexts e genfscon. No Android 7.0, a plataforma e o fornecedor usam
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, somente o fornecedor poderá rotular arquivos.
tmpfs (/dev)
Os arquivos em /dev podem ser rotulados em file_contexts. No Android 7.0, a plataforma e os arquivos de rótulo do fornecedor estão aqui.
Recomendação:o fornecedor pode rotular apenas arquivos em
/dev/vendor (por exemplo, /dev/vendor/foo,
/dev/vendor/socket/bar).
Rootfs (/)
Os arquivos em / podem ser rotulados em file_contexts. No Android
7.0, os arquivos de rótulo da plataforma e do fornecedor estão aqui.
Recomendação:somente o sistema pode rotular arquivos em /.
Dados (/data)
Os dados são rotulados por uma combinação de file_contexts e seapp_contexts.
Recomendação:não permita a rotulagem do fornecedor fora de
/data/vendor. Somente a plataforma pode rotular outras partes de
/data.
Versão dos rótulos do Genfs
A partir do nível da API do fornecedor 202504, os rótulos mais recentes do SELinux atribuídos com genfscon em system/sepolicy/compat/plat_sepolicy_genfs_ver.cil são opcionais para partições vendor mais antigas. Isso permite que partições
vendor mais antigas mantenham a implementação atual da SEPolicy.
Isso é controlado pela variável BOARD_GENFS_LABELS_VERSION do Makefile, que é armazenada em /vendor/etc/selinux/genfs_labels_version.txt.
Exemplo:
-
No nível da API do fornecedor 202404, o nó
/sys/class/udcé rotulado comosysfspor padrão. -
A partir do nível 202504 da API do fornecedor,
/sys/class/udcé rotulado comosysfs_udc.
No entanto, /sys/class/udc pode estar em uso por partições vendor
usando o nível da API 202404, com o rótulo sysfs
padrão ou um rótulo específico do fornecedor. Rotular incondicionalmente /sys/class/udc como sysfs_udc pode prejudicar a compatibilidade com essas partições vendor. Ao marcar BOARD_GENFS_LABELS_VERSION, a plataforma continua usando os rótulos e as permissões anteriores para as partições vendor mais antigas.
BOARD_GENFS_LABELS_VERSION pode ser maior ou igual ao nível da API do fornecedor. Por exemplo, as partições vendor que usam o nível da API 202404 podem definir BOARD_GENFS_LABELS_VERSION como 202504 para adotar novos rótulos introduzidos em 202504. Consulte a lista de
rótulos genfs específicos de 202504.
Ao rotular nós genfscon, a plataforma precisa considerar partições vendor mais antigas e implementar mecanismos de substituição para compatibilidade quando necessário. A plataforma pode usar bibliotecas exclusivas para consultar
a versão das rotulagens genfs.
-
Em nativo, use
libgenfslabelsversion. Consultegenfslabelsversion.hpara o arquivo principal delibgenfslabelsversion. -
Em Java, use
android.os.SELinux.getGenfsLabelsVersion().
Política pública da plataforma
A política do SELinux da plataforma é dividida em privada e pública. A política pública da plataforma consiste em tipos e atributos que estão sempre disponíveis para um nível da API do fornecedor, atuando como uma API entre a plataforma e o fornecedor. Essa política é exposta aos gravadores de políticas de fornecedores para permitir que eles criem arquivos de políticas de fornecedores que, quando combinados com a política privada da plataforma, resultam em uma política totalmente funcional para um dispositivo. A política pública da plataforma é definida em
system/sepolicy/public.
Por exemplo, um tipo vendor_init, que representa o processo de inicialização no contexto do fornecedor, é definido em system/sepolicy/public/vendor_init.te:
type vendor_init, domain;
Os fornecedores podem consultar o tipo vendor_init para escrever regras de política personalizadas:
# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)Atributos de compatibilidade
A política do SELinux é uma interação entre tipos de origem e destino para classes e permissões de objetos específicos. Cada objeto (por exemplo, processos, arquivos) 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. Aqui, vendor_init e debugfs são tipos:
allow vendor_init debugfs:dir { mounton };
Isso funciona porque a política foi escrita com conhecimento de todos os tipos. No entanto, se as políticas do fornecedor e 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 uma política que ganhou ou perdeu o acesso em que se baseava anteriormente. Por exemplo, suponha que a política da plataforma rotule os nós sysfs como sysfs:
/sys(/.*)? u:object_r:sysfs:s0
A política de fornecedores concede acesso a /sys/usb, rotulado como
sysfs:
allow vendor_init sysfs:chr_file rw_file_perms;
Se a política da plataforma for alterada para rotular /sys/usb como
sysfs_usb, a política do fornecedor vai permanecer a mesma, mas
vendor_init vai perder o acesso a /sys/usb devido à falta
de política para o novo tipo sysfs_usb:
/sys/usb u:object_r:sysfs_usb:s0
Para resolver esse problema, o Android introduz um conceito de atributos com versões. No tempo de compilação, o sistema de build traduz automaticamente os tipos públicos da plataforma usados na política do fornecedor para esses atributos versionados. Essa tradução é ativada por arquivos de mapeamento que associam um atributo com versão a um ou mais tipos públicos da plataforma.
Por exemplo, suponha que /sys/usb seja rotulado como sysfs
na política da plataforma 202504, e a política do fornecedor 202504 conceda
acesso vendor_init a /sys/usb. Nesse caso:
-
A política do fornecedor grava uma regra
allow vendor_init sysfs:chr_file rw_file_perms;porque/sys/usbé rotulado comosysfsna política da plataforma 202504. Quando o sistema de build compila a política do fornecedor, ele traduz automaticamente a regra paraallow vendor_init_202504 sysfs_202504:chr_file rw_file_perms;. Os atributosvendor_init_202504esysfs_202504correspondem aos tiposvendor_initesysfs, que são os tipos definidos pela plataforma. -
O sistema de build gera um arquivo de mapeamento de identidade
/system/etc/selinux/mapping/202504.cil. Como as partiçõessystemevendorusam a mesma versão202504, o arquivo de mapeamento contém mapeamentos de identidade detype_202504paratype. Por exemplo,vendor_init_202504é mapeado paravendor_initesysfs_202504é mapeado parasysfs:(typeattributeset sysfs_202504 (sysfs)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Quando a versão é atualizada de 202504 para 202604, um novo arquivo de mapeamento para partições vendor de 202504 é criado em system/sepolicy/private/compat/202504/202504.cil, que é instalado em /system/etc/selinux/mapping/202504.cil para as partições system de 202604 ou mais recentes. Inicialmente, esse arquivo contém mapeamentos de identidade, conforme descrito anteriormente. Se um novo rótulo sysfs_usb para /sys/usb for adicionado à política da plataforma 202604, o arquivo de mapeamento será atualizado para mapear sysfs_202504 para sysfs_usb:
(typeattributeset sysfs_202504 (sysfs sysfs_usb)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Com essa atualização, a regra de política do fornecedor convertida allow
vendor_init_202504 sysfs_202504:chr_file rw_file_perms; concede automaticamente
acesso vendor_init ao novo tipo sysfs_usb.
Para manter a compatibilidade com partições vendor mais antigas, sempre que um
novo tipo público for adicionado, ele precisará ser mapeado para pelo menos um dos atributos
com versão no arquivo de mapeamento system/sepolicy/private/compat/ver/ver.cil,
ou ser listado em system/sepolicy/private/compat/ver/ver.ignore.cil
para indicar que não há um tipo correspondente nas versões anteriores do fornecedor.
A combinação da política da plataforma, da política do fornecedor e do arquivo de mapeamento permite que o sistema seja atualizado sem atualizar a política do fornecedor. Além disso, a conversão em atributos versionados acontece automaticamente. Assim, a política do fornecedor não precisa cuidar do controle de versões, mantendo o uso dos tipos públicos no estado em que se encontra.
Política pública do sistema_ext e do produto
A partir do Android 11, as partições system_ext e product
podem exportar os tipos públicos designados para a partição
vendor. Assim como a política pública da plataforma, a política do fornecedor usa tipos e regras traduzidos automaticamente para os atributos versionados, por exemplo, de type para type_ver, em que ver é o nível da API do fornecedor da partição vendor.
Quando as partições system_ext e product são baseadas na mesma versão da plataforma ver, o sistema de build gera arquivos de mapeamento de base para system_ext/etc/selinux/mapping/ver.cil e product/etc/selinux/mapping/ver.cil, que contêm mapeamentos de identidade de type para type_ver.
A política do fornecedor pode acessar type com o atributo versionado
type_ver.
Se apenas as partições system_ext e product forem atualizadas, digamos, de ver para ver+1 (ou posterior), enquanto a partição vendor permanecer em ver, a política do fornecedor poderá perder o acesso aos tipos das partições system_ext e product. Para evitar falhas, as partições system_ext e product precisam fornecer arquivos de mapeamento de tipos concretos para atributos type_ver. Cada parceiro é responsável por manter os arquivos de mapeamento, caso ofereçam suporte à partição ver vendor com ver+1 (ou posterior) system_ext e product.
Para instalar arquivos de mapeamento nas partições system_ext e product,
os implementadores ou fornecedores de dispositivos precisam:
- Copie os arquivos de mapeamento de base gerados das partições ver,
system_exteproductpara a árvore de origem delas. - Faça alterações nos arquivos de mapeamento conforme necessário.
-
Instale os
arquivos de mapeamento para ver+1 (ou posterior)
system_exte partiçõesproduct.
Por exemplo, suponha que a partição 202504 system_ext tenha um
tipo público chamado foo_type. Então, system_ext/etc/selinux/mapping/202504.cil na partição 202504 system_ext fica assim:
(typeattributeset foo_type_202504 (foo_type)) (expandtypeattribute foo_type_202504 true) (typeattribute foo_type_202504)
Se bar_type for adicionado ao system_ext 202604 e se
bar_type precisar ser mapeado para foo_type na partição vendor 202504, 202504.cil poderá ser atualizado de
(typeattributeset foo_type_202504 (foo_type)) para
(typeattributeset foo_type_202504 (foo_type bar_type))
e instalado na partição system_ext 202604. A partição 202504
vendor pode continuar acessando o foo_type e o bar_type de 202604
system_ext.
Mudanças de atributos no Android 9
Os dispositivos que forem atualizados para o Android 9 podem usar os seguintes atributos, mas os dispositivos lançados com o Android 9 não podem.
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 a exigência de não compartilhar arquivos por caminho entrevendorecoredomains. Os processos de plataforma e fornecedor não devem usar arquivos no disco para se comunicar (ABI instável). Recomendação:- O código do fornecedor precisa usar
/data/vendor. - O sistema não deve usar
/data/vendor.
- O código do fornecedor precisa usar
system_executes_vendor_violators. Atributo para todos os domínios do sistema (excetoiniteshell domains) que violam o requisito de não executar binários do fornecedor. A execução de binários do fornecedor tem uma API instável. A plataforma não deve executar binários do fornecedor diretamente. Recomendação:- Essas dependências de plataforma em binários do fornecedor precisam estar por trás das HALs do HIDL.
OU
coredomainsque precisam de acesso a binários do fornecedor devem ser movidos para a partiçãovendore, assim, deixar de sercoredomain.
- Essas dependências de plataforma em binários do fornecedor precisam estar por trás das HALs do HIDL.
Atributos não confiáveis
Apps não confiáveis que hospedam código arbitrário não devem ter acesso a serviços do HwBinder, exceto aqueles considerados suficientemente seguros para acesso por esses apps (consulte os serviços seguros abaixo). Os dois principais motivos são:
- Os servidores HwBinder não realizam a autenticação do cliente porque o HIDL não expõe informações de UID do caller. Mesmo que o HIDL exponha esses dados, muitos serviços do HwBinder operam em um nível abaixo dos apps (como HALs) ou não podem depender da identidade do app para autorização. Portanto, para garantir a segurança, a proposição padrão é que todo serviço do HwBinder trate todos os clientes como igualmente autorizados a realizar operações oferecidas pelo serviço.
- Os servidores HAL (um subconjunto de serviços HwBinder) contêm código com uma taxa de incidência maior de problemas de segurança do que os componentes
system/coree têm acesso às camadas mais baixas da pilha (até o hardware), aumentando assim as oportunidades de ignorar 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 em que o processo é executado.coredomain_hwservice. Esses serviços não apresentam riscos associados ao motivo nº 2.hal_configstore_ISurfaceFlingerConfigs. Esse serviço foi projetado especificamente para uso em qualquer domínio.hal_graphics_allocator_hwservice. Essas operações também são oferecidas pelo serviço de vinculaçãosurfaceflinger, que os apps podem acessar.hal_omx_hwservice. Essa é uma versão do HwBinder do serviço Bindermediacodec, que os apps podem acessar.hal_codec2_hwservice, que é uma versão mais recente dehal_omx_hwservice.
Atributos utilizáveis
Todos os hwservices não considerados seguros têm o atributo
untrusted_app_visible_hwservice. Os servidores HAL correspondentes têm o atributo untrusted_app_visible_halserver. Os dispositivos lançados
com o Android 9 NÃO PODEM usar o atributo
untrusted.
Recomendação:
- Em vez disso, os apps não confiáveis precisam se comunicar com um serviço do sistema que se comunica com a
HAL HIDL do fornecedor. Por exemplo, os apps podem conversar com
binderservicedomain, emediaserver(que é umbinderservicedomain) conversa com ohal_graphics_allocator.OU
- Os apps que precisam de acesso direto aos HALs
vendordevem ter o próprio domínio de sepolicy definido pelo fornecedor.
Testes de atributos de arquivo
O Android 9 inclui testes de tempo de build que garantem que todos os arquivos em locais específicos tenham os atributos apropriados (por exemplo, todos os arquivos em sysfs têm o atributo sysfs_type obrigatório).
Rotulagem de contextos do SELinux
Para oferecer suporte à distinção entre a política do SELinux da plataforma e do fornecedor, o sistema cria arquivos de contexto do SELinux de maneira diferente para mantê-los separados.
Contextos de arquivo
O Android 8.0 introduziu as seguintes mudanças para file_contexts:
- Para evitar sobrecarga de compilação adicional no dispositivo durante a inicialização,
file_contextsdeixam de existir na forma binária. Em vez disso, eles são legíveis, arquivos de texto de expressão regular, como{property, service}_contexts(como eram antes da versão 7.0). - Os
file_contextssão divididos em dois arquivos:plat_file_contexts- Plataforma Android
file_contextsem rótulos específicos do dispositivo, exceto para rotular partes da partição/vendor, que precisam ser rotuladas com precisão para garantir o funcionamento adequado dos arquivos sepolicy. - Precisa estar na partição
systemem/system/etc/selinux/plat_file_contextsno dispositivo e ser carregado porinitno início junto com o vendorfile_context.
- Plataforma Android
vendor_file_contextsfile_contextespecífico do dispositivo criado combinandofile_contextsencontrado nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo.- Precisa ser instalado em
/vendor/etc/selinux/vendor_file_contextsna partiçãovendore carregado porinitno início, junto com a plataformafile_context.
Contextos de propriedade
No Android 8.0, o property_contexts é dividido em dois arquivos:
plat_property_contexts- Plataforma Android
property_contextsem rótulos específicos do dispositivo. - Precisa estar na partição
systemem/system/etc/selinux/plat_property_contextse ser carregado peloinitno início junto com oproperty_contextsdo fornecedor.
- Plataforma Android
vendor_property_contextsproperty_contextespecífico do dispositivo criado combinandoproperty_contextsencontrados nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo.- Precisa estar na partição
vendorem/vendor/etc/selinux/vendor_property_contextse ser carregado porinitno início junto com a plataformaproperty_context
Contextos de serviço
No Android 8.0, o service_contexts é dividido entre os seguintes
arquivos:
plat_service_contextsservice_contextespecífico da plataforma Android para oservicemanager. Oservice_contextnão tem rótulos específicos do dispositivo.- Precisa estar na partição
systemem/system/etc/selinux/plat_service_contextse ser carregado porservicemanagerno início junto com oservice_contextsdo fornecedor.
vendor_service_contextsservice_contextespecífico do dispositivo criado combinandoservice_contextsencontrado nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo.- Precisa estar na partição
vendorem/vendor/etc/selinux/vendor_service_contextse ser carregado peloservicemanagerno início, junto com a plataformaservice_contexts. - Embora o
servicemanagerprocure esse arquivo na inicialização, para um dispositivoTREBLEtotalmente compatível, ovendor_service_contextsNÃO PODE existir. Isso ocorre porque toda interação entre os processosvendoresystemPRECISA passar porhwservicemanager/hwbinder.
plat_hwservice_contexts- Plataforma Android
hwservice_contextparahwservicemanagersem rótulos específicos do dispositivo. - Precisa estar na partição
systemem/system/etc/selinux/plat_hwservice_contextse ser carregado porhwservicemanagerno início junto com ovendor_hwservice_contexts.
- Plataforma Android
vendor_hwservice_contextshwservice_contextespecífico do dispositivo criado combinandohwservice_contextsencontrado nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo.- Precisa estar na partição
vendorem/vendor/etc/selinux/vendor_hwservice_contextse ser carregado porhwservicemanagerno início junto com oplat_service_contexts.
vndservice_contextsservice_contextespecífico do dispositivo para ovndservicemanagercriado combinandovndservice_contextsencontrado nos diretórios apontados porBOARD_SEPOLICY_DIRSnoBoardconfig.mkdo dispositivo.- Esse arquivo precisa estar na partição
vendorem/vendor/etc/selinux/vndservice_contextse ser carregado porvndservicemanagerno início.
Contextos do Seapp
No Android 8.0, o seapp_contexts é dividido em dois arquivos:
plat_seapp_contexts- Plataforma Android
seapp_contextsem mudanças específicas do dispositivo. - Precisa estar na partição
systemem/system/etc/selinux/plat_seapp_contexts.
- Plataforma Android
vendor_seapp_contexts- Extensão específica do dispositivo para a plataforma
seapp_contextcriada combinandoseapp_contextsencontrados nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo. - Precisa estar na partição
vendorem/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 em dois arquivos:
- Plataforma
mac_permissions.xml- Plataforma Android
mac_permissions.xmlsem mudanças específicas do dispositivo. - Precisa estar na partição
systemem/system/etc/selinux/.
- Plataforma Android
- Não relacionada à plataforma
mac_permissions.xml- Extensão específica do dispositivo para a plataforma
mac_permissions.xmlcriada com base emmac_permissions.xmlencontrada nos diretórios apontados porBOARD_SEPOLICY_DIRSnos arquivosBoardconfig.mkdo dispositivo. - Precisa estar na partição
vendorem/vendor/etc/selinux/.
- Extensão específica do dispositivo para a plataforma
Mudanças na memória compartilhada para o Android 17
A partir do Android 17, os dispositivos lançados com as seguintes propriedades precisam ativar o recurso de política memfd_class e atualizar a política relacionada à memória compartilhada para oferecer suporte a objetos de classe memfd_file:
- Nível da API do fornecedor 202604 ou mais recente para dar aos fornecedores e OEMs a oportunidade de atualizar a política de fornecedores e oferecer suporte a
memfd. Ele também permite que os dispositivos atuais sejam atualizados para versões mais recentes do Android sem exigir uma atualização da partição do fornecedor. android16-6.12ou um kernel mais recente, já que eles são compatíveis com o recursomemfd_class, necessário para implementar uma política refinada paramemfd.
Ativar a capacidade da política memfd_class
Até recentemente, o SELinux rotulava um memfd como um arquivo do mesmo tipo que o sistema de arquivos de suporte, o tmpfs. Isso impossibilitou distinguir um memfd de outro arquivo em uma montagem tmpfs do ponto de vista da política. Agora, o SELinux rotula um memfd com o contexto de segurança do processo de alocação, e os memfds são tratados como objetos de classe memfd_file. Essa funcionalidade é protegida pela capacidade da política memfd_class para preservar a compatibilidade com versões anteriores em ambientes de espaço do usuário mais antigos.
Para ativar a capacidade da política memfd_class, crie um arquivo policy_capabilities em BOARD_VENDOR_SEPOLICY_DIRS. O arquivo precisa conter a seguinte entrada:
# $BOARD_VENDOR_SEPOLICY_DIRS/*/policy_capabilities
policycap memfd_class;Em seguida, recrie as imagens e atualize para o dispositivo para verificar se o recurso está ativado.
Verificar se o recurso de política memfd_class está ativado
Use o comando a seguir para verificar o status da capacidade da política memfd_class:
adb shell 'cat /sys/fs/selinux/policy_capabilities/memfd_class'
Se o resultado for 1, o recurso da política memfd_class estará ativado. Caso contrário, ele não será ativado.
Fazer a transição da política atual para memfd
Alguns processos usavam a macro tmpfs_domain() na política para acessar e criar namespaces para os memfds. Por exemplo:
# foo.te
tmpfs_domain(foo)Isso significa:
# foo.te type_transition foo tmpfs:file foo_tmpfs; allow foo foo_tmpfs:file { read write getattr map };
e permite processar o processo de acesso bar do processo foo como segue:memfds
# bar.te allow bar foo_tmpfs:file { read write getattr map };
Com o recurso de política memfd_class ativado, a macro tmpfs_domain() não é mais necessária, já que a política da plataforma foi atualizada para permitir que qualquer processo crie e use o próprio memfds, conforme mostrado aqui:
# system/sepolicy/private/domain.te allow domain self:memfd_file { create read write getattr map };
e memfds criado pelo processo foo pode ser acessado pelo processo bar da seguinte maneira:
# bar.te allow bar foo:memfd_file { read write getattr map };
A política da plataforma foi atualizada para considerar os usos atuais do memfd. No entanto, a política específica do fornecedor e do dispositivo que usa rótulos tmpfs precisa ser atualizada para usar memfd_file. Se a política for compartilhada entre SoCs ou dispositivos que não têm o nível 202604 da API do fornecedor ou mais recente, é recomendável manter a política legada tmpfs junto com a nova política memfd_file para compatibilidade.
Identificar negações de AVC relacionadas a memfd
As negações relacionadas a Memfd podem ser recuperadas usando o seguinte comando:
adb shell logcat -d -b events | grep memfd
negações de avc com tmpfs como destino
O exemplo a seguir mostra uma negação de avc encontrada por um processo que tentou gravar em um memfd sem permissão para isso:
audit(0.0:539): avc: denied { write } for comm="binder:665_1" name="memfd:MessageQueue"
dev="tmpfs" ino=8324 scontext=u:r:mediacodec:s0 tcontext=u:object_r:tmpfs:s0 tclass=file
permissive=0
Quando o recurso de política memfd_class está ativado, o contexto de destino de um memfd é o contexto de segurança do processo de alocação, não tmpfs, e a classe de destino é memfd_file, não file. Portanto, se você estiver observando negações de avc relacionadas a memfd, em que o memfd em questão é rotulado como um arquivo tmpfs, o recurso de política memfd_class não está ativado.
negações de avc com memfd_file como a classe de destino
O exemplo a seguir mostra uma negação de avc encontrada por um processo que tenta gravar em um memfd sem permissão para isso. O recurso de política memfd_class estava ativado, assim como uma linha adicional que o logd emite após a negação com a mesma marca de tempo:
audit(0.0:86): avc: denied { read } for
path=2F6D656D66643A4D6564696142756666657247726F7570202864656C6574656429 ino=512 dev=""
scontext=u:r:mediaserver:s0 tcontext=u:object_r:mediaextractor:s0 tclass=memfd_file
auditd : Decoded path for audit(0.0:86): /memfd:MediaBufferGroup (deleted)
O carimbo de data/hora correspondente indica que o Decoded path for … log está relacionado à negação de avc com o carimbo de data/hora 0.0.86. Esse registro decodifica a string hexadecimal do valor do caminho na negação avc e fornece o nome da região de memória memfd, o que pode ser útil para entender qual buffer está sendo compartilhado. O contexto de origem e o contexto de destino são úteis para entender quais processos precisam compartilhar memória. No exemplo anterior, fica claro que o processo mediaserver precisa acessar o memfds de mediaextractor. Portanto, a política adequada é:
# mediaserver.te allow mediaserver mediaextractor:memfd_file { getattr read write map };
Atualizações do domínio de segurança no Android 17
A API ASharedMemory_create() no Android 17 implementa lógica condicional para selecionar entre o driver ashmem legado e o framework memfd para alocações de memória compartilhada.
Para dispositivos que atendem aos requisitos de memfd (nível 202604 da API do fornecedor ou mais recente e kernel android16-6.12 ou mais recente), a API avalia o targetSdkVersion do app de chamada. Se a versão do SDK de destino for 37 ou mais recente, um memfd será alocado. Isso permite que os desenvolvedores corrijam os problemas encontrados ao fazer upgrade da versão do SDK de destino.
Se o dispositivo não atender aos pré-requisitos do memfd's, o ASharedMemory vai usar o ashmem. Isso mantém a compatibilidade para dispositivos atualizados com partições ou kernels de fornecedores mais antigos.
Para aplicar essa transição, a política do SELinux da plataforma impede que apps destinados à versão 37 ou mais recente do SDK nos domínios de segurança platform_app, priv_app e untrusted_app abram /dev/ashmem e invoquem comandos ioctl ashmem em memfd. Isso é feito dividindo esses domínios de app com base na versão do SDK de destino. Isso apresenta os domínios de segurança platform_app_36, priv_app_36 e untrusted_app_34, que, junto com outros domínios de apps, mantêm as permissões de abertura do ashmem e a capacidade de invocar comandos ioctl do ashmem em memfds.
Em uma versão futura do Android, o conjunto de apps que mantêm permissões para abrir o dispositivo ashmem e invocar comandos ioctl ashmem em memfds será reduzido apenas a platform_app_36, priv_app_36 e untrusted_app_34, além de domínios de apps não confiáveis para versões mais antigas do SDK.
As políticas personalizadas do fornecedor ou OEM do SELinux para apps que fixam a versão do SDK de destino precisam ser atualizadas para se alinhar a essas mudanças de domínio, conforme detalhado nas seções a seguir.
Atualizações do domínio SELinux platform_app
O domínio platform_app é dividido com base no targetSdkVersion do app. Os apps da plataforma destinados à versão 37 ou mais recente do SDK recebem o domínio platform_app, enquanto aqueles destinados à versão 36 ou anterior usam platform_app_36. O domínio platform_app_36 mantém a capacidade de abrir /dev/ashmem para compatibilidade com versões anteriores. Para simplificar o gerenciamento de políticas nos dois domínios, use o atributo platform_app_all.
Considere o caso em que o app da plataforma sample-plat-app precisa ler e gravar de e para /dev/foo_device. A política SELinux do fornecedor pode ser semelhante a esta:
# This will only allow sample-plat-app to access the device if it # is placed in the platform_app domain (i.e. target SDK version is 37 or higher). allow platform_app foo_device:chr_file rw_file_perms;
No entanto, se sample-plat-app for fixado na versão 36 do SDK de destino, ele será colocado no domínio platform_app_36, e a política do SELinux anterior não será aplicada. A seguinte negação de AVC será observada:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-plat-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:platform_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Para corrigir isso, a política pode ser atualizada da seguinte forma, já que o app sempre deve ter acesso ao nó do dispositivo:
# This allows sample-plat-app to access the device independent of # target SDK version. allow platform_app_all foo_device:chr_file rw_file_perms;
Há situações em que o platform_app_all pode não funcionar. Por exemplo, se a macro hal_client_domain() for usada com platform_app_all, a política não será compilada. Isso acontece porque platform_app_all é um atributo, e hal_client_domain() tentaria anexar outro atributo a ele, o que não é possível:
# platform_app.te
hal_client_domain(platform_app, hal_foo)
Nesses cenários, é necessário usar o tipo platform_app_36 diretamente. Portanto, sua política tem o seguinte conteúdo:
# platform_app.te hal_client_domain(platform_app, hal_foo) # platform_app_36.te hal_client_domain(platform_app_36, hal_foo)
Atualizações do domínio SELinux priv_app
O domínio priv_app é dividido com base no targetSdkVersion do app. Os apps privilegiados destinados à versão 37 do SDK ou mais recente recebem o domínio priv_app, enquanto aqueles destinados à versão 36 ou anterior usam priv_app_36. O domínio priv_app_36 mantém a capacidade de abrir /dev/ashmem para compatibilidade com versões anteriores. Para simplificar o gerenciamento de políticas nos dois domínios, use o atributo priv_app_all.
Considere o caso em que o app da plataforma sample-priv-app precisa ler e gravar de e para /dev/foo_device. A política SELinux do fornecedor pode ser semelhante a esta:
# This will only allow sample-priv-app to access the device if it # is placed in the priv_app domain (i.e. target SDK version is 37 or higher). allow priv_app foo_device:chr_file rw_file_perms;
No entanto, se sample-priv-app for fixado na versão 36 do SDK de destino, ele será colocado no domínio priv_app_36, e a política do SELinux anterior não será aplicada. A seguinte negação de AVC será observada:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-priv-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:priv_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Para corrigir isso, a política pode ser atualizada da seguinte forma, já que o app sempre deve ter acesso ao nó do dispositivo:
# This allows sample-priv-app to access the device independent of # target SDK version. allow priv_app_all foo_device:chr_file rw_file_perms;
Há situações em que o priv_app_all pode não funcionar. Por exemplo, se a macro hal_client_domain() for usada com priv_app_all, a política não será compilada. Isso acontece porque priv_app_all é um atributo, e hal_client_domain() tentaria anexar outro atributo a ele, o que não é possível:
# priv_app.te
hal_client_domain(priv_app, hal_foo)
Nesses cenários, é necessário usar o tipo priv_app_36 diretamente. Assim, os arquivos de política vão ficar assim:
# priv_app.te hal_client_domain(priv_app, hal_foo) # priv_app_36.te hal_client_domain(priv_app_36, hal_foo)
Atualizações do domínio SELinux untrusted_app
O domínio untrusted_app é dividido com base no targetSdkVersion do app. Os apps não confiáveis destinados à versão 37 do SDK ou mais recente recebem o domínio untrusted_app, enquanto aqueles destinados às versões 34 a 36, inclusive, recebem o novo domínio untrusted_app_34. O domínio untrusted_app_34, assim como os domínios untrusted_app_X, em que "X" é uma versão mais antiga do SDK de destino, mantêm a capacidade de abrir `/dev/ashmem` para compatibilidade com versões anteriores.