Os objetos e serviços do sistema de arquivos adicionados à compilação geralmente precisam de IDs exclusivos e separados, conhecidos como IDs do Android (AIDs). Atualmente, muitos recursos, como arquivos e serviços, usam AIDs principais (definidos pelo Android) desnecessariamente; em muitos casos, você pode usar AIDs OEM (definidos pelo OEM) em vez disso.
Versões anteriores do Android (Android 7.xe inferior) estenderam o mecanismo de AIDs usando um arquivo android_filesystem_config.h específico do dispositivo para especificar recursos do sistema de arquivos e/ou AIDs OEM personalizados. No entanto, esse sistema não era intuitivo, pois não suportava o uso de nomes agradáveis para AIDs OEM, exigindo que você especificasse o numérico bruto para campos de usuário e grupo sem uma maneira de associar um nome amigável ao AID numérico.
As versões mais recentes do Android (Android 8.0 e superior) oferecem suporte a um novo método para estender os recursos do sistema de arquivos. Este novo método tem suporte para o seguinte:
- Vários locais de origem para arquivos de configuração (permite configurações de compilação extensíveis).
- Verificação de sanidade em tempo de construção dos valores de OEM AID.
- Geração de um cabeçalho OEM AID personalizado que pode ser usado em arquivos de origem conforme necessário.
- Associação de um nome amigável com o valor real do OEM AID. Suporta argumentos de string não numéricos para usuário e grupo, ou seja, "foo" em vez de "2901".
Melhorias adicionais incluem a remoção do array android_ids[] de system/core/libcutils/include/private/android_filesystem_config.h . Esse array agora existe no Bionic como um array gerado totalmente privado, com acessadores via getpwnam() e getgrnam() . (Isso tem o efeito colateral de produzir binários estáveis à medida que os AIDs principais são modificados.) Para ferramentas e um arquivo README com mais detalhes, consulte build/make/tools/fs_config .
Adicionando IDs do Android (AIDs)
O Android 8.0 removeu a matriz android_ids[] do Android Open Source Project (AOSP). Todos os nomes compatíveis com AID são gerados a partir do arquivo de cabeçalho system/core/libcutils/include/private/android_filesystem_config.h ao gerar o array Bionic android_ids[] . Qualquer define correspondente AID_* é selecionada pelo conjunto de ferramentas e * se torna o nome em minúsculas.
Por exemplo, em private/android_filesystem_config.h :
#define AID_SYSTEM 1000
Torna-se:
- Nome amigável: sistema
- uid: 1000
- gid: 1000
Para adicionar um novo AOSP core AID, basta adicionar o #define ao arquivo de cabeçalho android_filesystem_config.h . O AID será gerado na compilação e disponibilizado para interfaces que usam argumentos de usuário e grupo. O ferramental valida que o novo AID não está dentro das faixas de APP ou OEM; ele também respeita as alterações nesses intervalos e deve ser reconfigurado automaticamente nas alterações ou nos novos intervalos reservados ao OEM.
Configurando AIDs
Para habilitar o novo mecanismo de AIDs, defina TARGET_FS_CONFIG_GEN no arquivo BoardConfig.mk . Essa variável contém uma lista de arquivos de configuração, permitindo anexar arquivos conforme necessário.
Por convenção, os arquivos de configuração usam o nome config.fs , mas na prática você pode usar qualquer nome. Os arquivos config.fs estão no formato Python ConfigParser ini e incluem uma seção caps (para configurar recursos do sistema de arquivos) e uma seção AIDs (para configurar AIDs OEM).
Configurando a seção de maiúsculas
A seção caps suporta a configuração de recursos do sistema de arquivos em objetos do sistema de arquivos dentro da compilação (o próprio sistema de arquivos também deve suportar essa funcionalidade).
Como a execução de um serviço estável como root no Android causa uma falha do Compatibility Test Suite (CTS) , os requisitos anteriores para reter um recurso durante a execução de um processo ou serviço envolviam configurar recursos e usar setuid / setgid para um AID adequado para execução. Com caps, você pode pular esses requisitos e fazer com que o kernel faça isso por você. Quando o controle é passado para main() , seu processo já possui os recursos necessários para que seu serviço possa usar um usuário e grupo não root (essa é a maneira preferida de iniciar serviços privilegiados).
A seção caps usa a seguinte sintaxe:
| Seção | Valor | Definição |
|---|---|---|
[path] | O caminho do sistema de arquivos a ser configurado. Um caminho que termina em / é considerado um dir, senão é um arquivo. É um erro especificar várias seções com o mesmo [path] em arquivos diferentes. Nas versões do Python <= 3.2, o mesmo arquivo pode conter seções que substituem a seção anterior; no Python 3.2, está definido para o modo estrito. | |
mode | Modo de arquivo octal | Um modo de arquivo octal válido de pelo menos 3 dígitos. Se 3 for especificado, será prefixado com 0, senão o modo será usado como está. |
user | AID_<usuário> | O C define para um AID válido ou o nome amigável (por exemplo, AID_RADIO e radio são aceitáveis). Para definir um AID personalizado, consulte a seção Configurando o AID . |
group | AID_<grupo> | O mesmo que usuário. |
caps | boné* | O nome declarado em bionic/libc/kernel/uapi/linux/capability.h sem o CAP_ . Caso misto permitido. As tampas também podem ser o bruto:
|
Para obter um exemplo de uso, consulte Usando recursos do sistema de arquivos .
Configurando a seção AID
A seção AID contém AIDs OEM e usa a seguinte sintaxe:
| Seção | Valor | Definição |
|---|---|---|
[AID_<name>] | O <name> pode conter caracteres em maiúsculas, números e sublinhados. A versão em minúsculas é usada como nome amigável. O arquivo de cabeçalho gerado para inclusão de código usa o AID_<name> exato.É um erro especificar várias seções com o mesmo AID_<name> (não diferencia maiúsculas de minúsculas com as mesmas restrições que [path] ).<name> deve começar com um nome de partição para garantir que não entre em conflito com fontes diferentes. | |
value | <número> | Uma string de número de estilo C válida (hex, octal, binário e decimal). É um erro especificar várias seções com a mesma opção de valor. As opções de valor devem ser especificadas no intervalo correspondente à partição usada em <name> . A lista de partições válidas e seus intervalos correspondentes é definida em system/core/libcutils/include/private/android_filesystem_config.h . As opções são:
|
Para exemplos de uso, consulte Definindo nomes de OEM AID e Usando OEM AIDs .
Exemplos de uso
Os exemplos a seguir detalham como definir e usar um OEM AID e como habilitar os recursos do sistema de arquivos. Os nomes de OEM AID ( [AID_ name ] ) devem começar com um nome de partição, como " fornecedor_ " para garantir que não entrem em conflito com futuros nomes de AOSP ou outras partições.
Definindo nomes de OEM AID
Para definir um OEM AID, crie um arquivo config.fs e defina o valor do AID. Por exemplo, em device/x/y/config.fs , defina o seguinte:
[AID_VENDOR_FOO] value: 2900
Após criar o arquivo, defina a variável TARGET_FS_CONFIG_GEN e aponte para ela em BoardConfig.mk . Por exemplo, em device/x/y/BoardConfig.mk , defina o seguinte:
TARGET_FS_CONFIG_GEN += device/x/y/config.fs
Seu AID personalizado agora pode ser consumido pelo sistema em geral em uma nova compilação.
Usando AIDs OEM
Para usar um OEM AID, em seu código C, inclua o oemaids_headers em seu Makefile associado e adicione #include "generated_oem_aid.h" e comece a usar os identificadores declarados. Por exemplo, em my_file.c , adicione o seguinte:
#include "generated_oem_aid.h"
…
If (ipc->uid == AID_VENDOR_FOO) {
// Do something
...
Em seu arquivo Android.bp associado, adicione o seguinte:
header_libs: ["oemaids_headers"],
Se você estiver usando um arquivo Android.mk , adicione o seguinte:
LOCAL_HEADER_LIBRARIES := oemaids_headers
Usando nomes amigáveis
No Android 9, você pode usar o nome amigável para qualquer interface compatível com nomes de AID. Por exemplo:
- Em um comando
chownemsome/init.rc:chown vendor_foo /vendor/some/vendor_foo/file
- Em um
serviceemsome/init.rc:service vendor_foo /vendor/bin/foo_service user vendor_foo group vendor_foo
Como o mapeamento interno do nome amigável para o uid é executado por /vendor/etc/passwd e /vendor/etc/group , a partição do fornecedor deve ser montada.
Associando nomes amigáveis
O Android 9 inclui suporte para associar um nome amigável ao valor real do OEM AID. Você pode usar argumentos de string não numéricos para usuário e grupo, ou seja, " fornecedor_foo " em vez de "2901".
Convertendo de AID para nomes amigáveis
Para AIDs de OEM , o Android 8.x exigia o uso de oem_#### com getpwnam e funções semelhantes, bem como em locais que lidam com pesquisas via getpwnam (como scripts de init ). No Android 9, você pode usar os amigos getpwnam e getgrnam no Bionic para converter de IDs do Android (AIDs) para nomes amigáveis e vice-versa.
Usando recursos do sistema de arquivos
Para habilitar os recursos do sistema de arquivos, crie uma seção caps no arquivo config.fs . Por exemplo, em device/x/y/config.fs , adicione a seguinte seção:
[system/bin/foo_service] mode: 0555 user: AID_VENDOR_FOO group: AID_SYSTEM caps: SYS_ADMIN | SYS_NICE
Após criar o arquivo, defina o TARGET_FS_CONFIG_GEN para apontar para esse arquivo em BoardConfig.mk . Por exemplo, em device/x/y/BoardConfig.mk , defina o seguinte:
TARGET_FS_CONFIG_GEN += device/x/y/config.fs
Quando o serviço vendor_ foo é executado, ele inicia com os recursos CAP_SYS_ADMIN e CAP_SYS_NICE sem chamadas setuid e setgid . Além disso, a política SELinux do serviço vendor_ foo não precisa mais do recurso setuid e setgid e pode ser excluída.
Como configurar substituições (Android 6.x-7.x)
O Android 6.0 realocou fs_config e definições de estrutura associadas ( system/core/include/private/android_filesystem_config.h ) para system/core/libcutils/fs_config.c onde eles podem ser atualizados ou substituídos por arquivos binários instalados em /system/etc/fs_config_dirs e /system/etc/fs_config_files . O uso de regras separadas de correspondência e análise para diretórios e arquivos (que podem usar expressões glob adicionais) permitiu que o Android lidasse com diretórios e arquivos em duas tabelas diferentes. As definições de estrutura em system/core/libcutils/fs_config.c não apenas permitiam a leitura de diretórios e arquivos em tempo de execução, mas o host poderia usar os mesmos arquivos durante o tempo de compilação para construir imagens do sistema de arquivos como ${OUT}/system/etc/fs_config_dirs e ${OUT}/system/etc/fs_config_files .
Embora o método de substituição de extensão do sistema de arquivos tenha sido substituído pelo sistema de configuração modular introduzido no Android 8.0, você ainda pode usar o método antigo, se desejar. As seções a seguir detalham como gerar e incluir arquivos de substituição e configurar o sistema de arquivos.
Gerando arquivos de substituição
Você pode gerar os arquivos binários alinhados /system/etc/fs_config_dirs e /system/etc/fs_config_files usando a ferramenta fs_config_generate em build/tools/fs_config . A ferramenta usa uma função de biblioteca libcutils ( fs_config_generate() ) para gerenciar os requisitos de DAC em um buffer e define regras para um arquivo de inclusão para institucionalizar as regras de DAC.
Para usar, crie um arquivo de inclusão em device/ vendor / device /android_filesystem_config.h que atua como substituição. O arquivo deve usar o formato de structure fs_path_config definido em system/core/include/private/android_filesystem_config.h com as seguintes inicializações de estrutura para símbolos de diretório e arquivo:
- Para diretórios, use
android _device _dirs[]. - Para arquivos, use
android _device _files[].
Quando não estiver usando android_device_dirs[] e android_device_files[] , você pode definir NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS e NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (veja o exemplo abaixo). Você também pode especificar o arquivo de substituição usando TARGET_ANDROID_FILESYSTEM_CONFIG_H na configuração da placa, com um nome de base obrigatório de android_filesystem_config.h .
Incluindo arquivos de substituição
Para incluir arquivos, certifique-se de que PRODUCT_PACKAGES inclua fs_config_dirs e/ou fs_config_files para que possa instalá-los em /system/etc/fs_config_dirs e /system/etc/fs_config_files , respectivamente. O sistema de compilação procura android_filesystem_config.h personalizado em $(TARGET_DEVICE_DIR) , onde existe BoardConfig.mk . Se este arquivo existir em outro lugar, defina a variável de configuração da placa TARGET_ANDROID_FILESYSTEM_CONFIG_H para apontar para esse local.
Configurando o sistema de arquivos
Para configurar o sistema de arquivos no Android 6.0 e superior:
- Crie o arquivo
$(TARGET_DEVICE_DIR)/android_filesystem_config.h. - Adicione os
fs_config_dirse/oufs_config_filesaPRODUCT_PACKAGESno arquivo de configuração da placa (por exemplo,$(TARGET_DEVICE_DIR)/device.mk).
Substituir exemplo
Este exemplo mostra um patch para substituir o daemon system/bin/glgps para adicionar suporte a wake lock no diretório device/ vendor / device . Tenha em mente o seguinte:
- Cada entrada de estrutura é o modo, uid, gid, capacidades e o nome.
system/core/include/private/android_filesystem_config.hé incluído automaticamente para fornecer o manifesto #defines (AID_ROOT,AID_SHELL,CAP_BLOCK_SUSPEND). - A seção
android_device_files[]inclui uma ação para suprimir o acesso asystem/etc/fs_config_dirsquando não especificado, que serve como uma proteção adicional de DAC por falta de conteúdo para substituições de diretório. No entanto, esta é uma proteção fraca; se alguém tem controle sobre/system, eles normalmente podem fazer o que quiserem.
diff --git a/android_filesystem_config.h b/android_filesystem_config.h
new file mode 100644
index 0000000..874195f
--- /dev/null
+++ b/android_filesystem_config.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (eg: mkbootfs) and
+** by the device side of adb.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+/* static const struct fs_path_config android_device_dirs[] = { }; */
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_device_files[] = {
+ { 00755, AID_ROOT, AID_SHELL, (1ULL << CAP_BLOCK_SUSPEND),
"system/bin/glgps" },
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+ { 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },
+#endif
+};
diff --git a/device.mk b/device.mk
index 0c71d21..235c1a7 100644
--- a/device.mk
+++ b/device.mk
@@ -18,7 +18,8 @@ PRODUCT_PACKAGES := \
libwpa_client \
hostapd \
wpa_supplicant \
- wpa_supplicant.conf
+ wpa_supplicant.conf \
+ fs_config_files
ifeq ($(TARGET_PREBUILT_KERNEL),)
ifeq ($(USE_SVELTE_KERNEL), true)
Migrando sistemas de arquivos de versões anteriores
Ao migrar sistemas de arquivos do Android 5.xe anteriores, lembre-se de que o Android 6.x
- Remove algumas inclusões, estruturas e definições embutidas.
- Requer uma referência a
libcutilsem vez de ser executado diretamente desystem/core/include/private/android_filesystem_config.h. Os executáveis privados do fabricante do dispositivo que dependem desystem/code/include/private_filesystem_config.hpara as estruturas de arquivo ou diretório oufs_configdevem adicionar dependências da bibliotecalibcutils. - Requer cópias de ramificação privada do fabricante do dispositivo do
system/core/include/private/android_filesystem_config.hcom conteúdo extra em destinos existentes para mover paradevice/ vendor / device /android_filesystem_config.h. - Reserva-se o direito de aplicar o SELinux Mandatory Access Controls (MAC) aos arquivos de configuração no sistema de destino, implementações que incluem executáveis de destino personalizados usando
fs_config()devem garantir o acesso.