Controle de acesso discricionário (DAC)

Objetos e serviços do sistema de arquivos adicionados ao build geralmente precisam de IDs separados e exclusivos, conhecidos como IDs do Android (AIDs). Atualmente, muitos recursos, como arquivos e serviços, usam AIDs principais (definidos pelo Android) desnecessariamente. Em muitos casos, é possível usar AIDs OEM (definidos pelo OEM).

As versões anteriores do Android (Android 7.x e anteriores) estenderam o mecanismo de AIDs usando um arquivo android_filesystem_config.h específico do dispositivo para especificar funcionalidades do sistema de arquivos e/ou AIDs personalizados do OEM. No entanto, esse sistema não era intuitivo porque não permitia o uso de nomes conhecidos para AIDs de OEM. Era necessário especificar o valor numérico bruto para os campos de usuário e grupo sem uma maneira de associar um nome conhecido ao AID numérico.

Versões mais recentes do Android (Android 8.0 e mais recentes) oferecem suporte a um novo método para ampliar os recursos do sistema de arquivos. Esse novo método é compatível com o seguinte:

  • Vários locais de origem para arquivos de configuração (permite configurações de build extensíveis).
  • Verificação de integridade no momento da build dos valores de AID do OEM.
  • Geração de um cabeçalho AID OEM personalizado que pode ser usado em arquivos de origem conforme necessário.
  • Associação de um nome amigável ao valor real do AID do OEM. Aceita argumentos de string não numéricos para usuário e grupo, ou seja, "foo" em vez de "2901".

Outras melhorias incluem a remoção da matriz android_ids[] de system/core/libcutils/include/private/android_filesystem_config.h. Essa matriz agora existe no Bionic como uma matriz gerada totalmente particular, com acessadores com getpwnam() e getgrnam(). Isso tem o efeito colateral de produzir binários estáveis à medida que os AID principais são modificados. Para ferramentas e um arquivo README com mais detalhes, consulte build/make/tools/fs_config.

Adicionar IDs do Android (AIDs)

O Android 8.0 removeu a matriz android_ids[] do Android Open Source Project (AOSP). Em vez disso, todos os nomes compatíveis com AID são gerados do arquivo de cabeçalho system/core/libcutils/include/private/android_filesystem_config.h ao gerar a matriz android_ids[] do Bionic. Qualquer define que corresponda a AID_* é capturada pelas ferramentas e * se torna o nome em letras minúsculas.

Por exemplo, em private/android_filesystem_config.h:

#define AID_SYSTEM 1000

O resultado é:

  • Nome amigável: sistema
  • uid: 1000
  • gid: 1000

Para adicionar uma nova AID principal do AOSP, basta incluir #define no arquivo de cabeçalho android_filesystem_config.h. O AID é gerado no build e disponibilizado para interfaces que usam argumentos de usuário e grupo. A ferramenta valida se o novo AID não está nos intervalos do APP ou do OEM. Ela também respeita as mudanças nesses intervalos e se reconfigura automaticamente em caso de mudanças ou novos intervalos reservados pelo OEM.

Configurar AIDs

Para ativar 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 que você adicione 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 ini do Python ConfigParser e incluem uma seção de recursos (para configurar as funcionalidades do sistema de arquivos) e uma seção de AIDs (para configurar os AIDs do OEM).

Configurar a seção de maiúsculas

A seção de recursos permite definir capacidades do sistema de arquivos em objetos do sistema de arquivos na build. O próprio sistema de arquivos também precisa oferecer suporte a essa funcionalidade.

Como a execução de um serviço estável como root no Android causa uma falha no conjunto de teste de compatibilidade (CTS), os requisitos anteriores para reter uma capacidade ao executar um processo ou serviço envolviam a configuração de recursos e o uso de setuid/setgid para um AID adequado para execução. Com as capacidades, você pode pular esses requisitos e deixar que o kernel faça isso por você. Quando o controle é transferido para main(), seu processo já tem os recursos necessários para que o serviço use um usuário e um grupo não raiz. Essa é a maneira preferida de iniciar serviços privilegiados.

A seção de maiúsculas 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 diretório, caso contrário, é um arquivo.

É um erro especificar várias seções com o mesmo [path] em arquivos diferentes. Em versões do Python <= 3.2, o mesmo arquivo pode conter seções que substituem a seção anterior. No Python 3.2, ele é definido como modo estrito.
mode Modo de arquivo octal Um modo de arquivo octal válido de pelo menos três dígitos. Se 3 for especificado, ele vai receber o prefixo 0. Caso contrário, o modo será usado como está.
user AID_<user> 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 Configurar a seção AID.
group AID_<group> Igual a "user".
caps cap* O nome declarado em bionic/libc/kernel/uapi/linux/capability.h sem o CAP_ inicial. É permitido usar maiúsculas e minúsculas. As maiúsculas também podem ser o valor bruto:
  • binário (0b0101)
  • octal (0455)
  • int (42)
  • hex (0xFF)
Separe várias maiúsculas usando espaços em branco.

Para um exemplo de uso, consulte Como usar recursos do sistema de arquivos.

Configurar a seção AID

A seção AID contém AIDs de OEM e usa a seguinte sintaxe:

Seção Valor Definição
[AID_<name>] O <name> pode conter caracteres do conjunto maiúsculas, números e sublinhados. A versão em letras minúsculas é usada como o 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> (sem diferenciação de maiúsculas e minúsculas, com as mesmas restrições de [path]).

<name> precisa começar com um nome de partição para garantir que não haja conflito com fontes diferentes.
value <número> Uma string de número válida no estilo C (hexadecimal, octal, binário e decimal).

É um erro especificar várias seções com a mesma opção de valor.

As opções de valor precisam ser especificadas no intervalo correspondente à partição usada em <name>. A lista de partições válidas e os intervalos correspondentes são definidos em system/core/libcutils/include/private/android_filesystem_config.h. As opções são:
  • Partição do fornecedor
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • Partição do sistema
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • Partição ODM
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • Partição de produtos
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • Partição system_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

Para exemplos de uso, consulte Definir nomes de AID do OEM e Usar AIDs do OEM.

Exemplos de uso

Os exemplos a seguir detalham como definir e usar um AID do OEM e como ativar recursos do sistema de arquivos. Os nomes de AID do OEM ([AID_name]) precisam começar com um nome de partição, como "vendor_", para não entrar em conflito com nomes futuros do AOSP ou outras partições.

Definir nomes de AID do OEM

Para definir um AID do OEM, 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

Depois de 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 usado pelo sistema em geral em um novo build.

Usar AIDs OEM

Para usar um AID do OEM, no código C, inclua o oemaids_headers no Makefile associado e adicione #include "generated_oem_aid.h". Depois, 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
...

No 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

Usar nomes fáceis de lembrar

No Android 9, é possível usar o nome amigável para qualquer interface que ofereça suporte a nomes de AID. Exemplo:

  • Em um comando chown no some/init.rc:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • Em um service em some/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 é realizado por /vendor/etc/passwd e /vendor/etc/group, a partição do fornecedor precisa ser montada.

Associar nomes amigáveis

O Android 9 inclui suporte para associar um nome amigável ao valor real do AID do OEM. É possível usar argumentos de string não numérica para usuário e grupo, ou seja, "vendor_foo" em vez de "2901".

Converter de AID para nomes fáceis de lembrar

Para AIDs de OEM, o Android 8.x exigia o uso de oem_#### com getpwnam e funções semelhantes, bem como em lugares que processam pesquisas com getpwnam (como scripts init). No Android 9, é possível usar os amigos getpwnam e getgrnam no Bionic para converter de IDs do Android (AIDs) para nomes amigáveis e vice-versa.

Usar recursos do sistema de arquivos

Para ativar 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

Depois de 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 começa com as funcionalidades CAP_SYS_ADMIN e CAP_SYS_NICE sem chamadas setuid e setgid. Além disso, a política do SELinux do serviço vendor_foo não precisa mais das capacidades setuid e setgid e pode ser excluída.

Configurar substituições (Android 6.x a 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 podiam ser atualizadas ou substituídas 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 processasse diretórios e arquivos em duas tabelas diferentes. As definições de estrutura em system/core/libcutils/fs_config.c não permitiam apenas a leitura de diretórios e arquivos em tempo de execução, mas o host podia usar os mesmos arquivos durante o tempo de build 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 para estender o sistema de arquivos tenha sido substituído pelo sistema de configuração modular introduzido no Android 8.0, ainda é possível usar o método antigo, se quiser. As seções a seguir detalham como gerar e incluir arquivos de substituição e configurar o sistema de arquivos.

Gerar arquivos de substituição

É possível 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 institucionalizar as regras de DAC.

Para usar, crie um arquivo de inclusão em device/vendor/device/android_filesystem_config.h que funcione como a substituição. O arquivo precisa usar o formato 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 usar android_device_dirs[] e android_device_files[], você poderá definir NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS e NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (confira o exemplo abaixo). Também é possível especificar o arquivo de substituição usando TARGET_ANDROID_FILESYSTEM_CONFIG_H na configuração da placa, com um nome base forçado de android_filesystem_config.h.

Incluir arquivos de substituição

Para incluir arquivos, verifique se PRODUCT_PACKAGES inclui 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 build pesquisa android_filesystem_config.h personalizados em $(TARGET_DEVICE_DIR), onde BoardConfig.mk existe. Se esse arquivo existir em outro lugar, defina a variável de configuração da placa TARGET_ANDROID_FILESYSTEM_CONFIG_H para apontar para esse local.

Configurar o sistema de arquivos

Para configurar o sistema de arquivos no Android 6.0 e versões mais recentes:

  1. Crie o arquivo $(TARGET_DEVICE_DIR)/android_filesystem_config.h.
  2. Adicione fs_config_dirs e/ou fs_config_files a PRODUCT_PACKAGES no arquivo de configuração da placa (por exemplo, $(TARGET_DEVICE_DIR)/device.mk).

Exemplo de substituição

Este exemplo mostra um patch para substituir o daemon system/bin/glgps e adicionar suporte ao bloqueio de despertar no diretório device/vendor/device. Lembre-se do seguinte:

  • Cada entrada de estrutura é o modo, uid, gid, recursos e o nome. system/core/include/private/android_filesystem_config.h é incluído automaticamente para fornecer as #defines do manifesto (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • A seção android_device_files[] inclui uma ação para suprimir o acesso a system/etc/fs_config_dirs quando não especificado, o que serve como uma proteção DAC adicional por falta de conteúdo para substituições de diretório. No entanto, essa proteção é fraca. Se alguém tiver controle sobre /system, geralmente poderá fazer o que quiser.
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 file system
+** 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)

Migrar sistemas de arquivos de versões anteriores

Ao migrar sistemas de arquivos do Android 5.x e versões anteriores, lembre-se de que o Android 6.x

  • Remove alguns includes, estruturas e definições inline.
  • Exige uma referência a libcutils em vez de ser executado diretamente de system/core/include/private/android_filesystem_config.h. Executáveis particulares do fabricante do dispositivo que dependem de system/code/include/private_filesystem_config.h para as estruturas de arquivo ou diretório ou fs_config precisam adicionar dependências da biblioteca libcutils.
  • Exige cópias de ramificação privada do fabricante do dispositivo do system/core/include/private/android_filesystem_config.h com conteúdo extra em destinos atuais para migrar para device/vendor/device/android_filesystem_config.h.
  • Reserva o direito de aplicar controles de acesso obrigatório (MAC) do SELinux a arquivos de configuração no sistema de destino. Implementações que incluem executáveis de destino personalizados usando fs_config() precisam garantir o acesso.