Controle de acesso discricionário (DAC)

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:
  • binário (0b0101)
  • octal (0455)
  • int (42)
  • hex (0xFF)
Separe várias maiúsculas usando espaços em branco.

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:
  • 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 do produto
    • 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 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 chown em 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 é 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:

  1. Crie o arquivo $(TARGET_DEVICE_DIR)/android_filesystem_config.h .
  2. Adicione os 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 ).

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 a system/etc/fs_config_dirs quando 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 libcutils em vez de ser executado diretamente de system/core/include/private/android_filesystem_config.h . Os executáveis ​​privados 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 devem adicionar dependências da biblioteca libcutils .
  • Requer 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 existentes para mover para device/ 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.