Control de acceso discrecional (DAC)

Los objetos y servicios del sistema de archivos que se agregan a la compilación suelen necesitar IDs únicos y separados, conocidos como IDs de Android (AID). Actualmente, muchos recursos, como archivos y servicios, usan AIDs principales (definidos por Android) de forma innecesaria. En muchos casos, puedes usar AIDs de OEM (definidos por el OEM) en su lugar.

Las versiones anteriores de Android (Android 7.x y versiones anteriores) extendieron el mecanismo de AIDs con un archivo android_filesystem_config.h específico del dispositivo para especificar las capacidades del sistema de archivos o los AIDs de OEM personalizados. Sin embargo, este sistema no era intuitivo, ya que no admitía el uso de nombres descriptivos para los AIDs de OEM, lo que te obligaba a especificar el número sin procesar para los campos de usuario y grupo sin una forma de asociar un nombre descriptivo con el AID numérico.

Las versiones más recientes de Android (Android 8.0 y versiones posteriores) admiten un método nuevo para extender las capacidades del sistema de archivos. Este nuevo método admite lo siguiente:

  • Múltiples ubicaciones de origen para los archivos de configuración (permite configuraciones de compilación extensibles).
  • Verificación de coherencia en el tiempo de compilación de los valores de AID del OEM.
  • Generación de un encabezado de AID de OEM personalizado que se puede usar en los archivos fuente según sea necesario
  • Asociación de un nombre fácil de usar con el valor real del AID del OEM. Admite argumentos de cadena no numérica para el usuario y el grupo, es decir, "foo" en lugar de "2901".

Entre las mejoras adicionales, se incluye la eliminación del array android_ids[] de system/core/libcutils/include/private/android_filesystem_config.h. Este array ahora existe en Bionic como un array generado completamente privado, con accesores con getpwnam() y getgrnam(). (Esto tiene el efecto secundario de producir objetos binarios estables a medida que se modifican los AID principales). Para ver las herramientas y un archivo README con más detalles, consulta build/make/tools/fs_config.

Agregar IDs de Android (AIDs)

En Android 8.0, se quitó el arreglo android_ids[] del Proyecto de código abierto de Android (AOSP). En cambio, todos los nombres compatibles con AID se generan desde el archivo de encabezado system/core/libcutils/include/private/android_filesystem_config.h cuando se genera el array android_ids[] de Bionic. Las herramientas detectan cualquier define que coincida con AID_*, y * se convierte en el nombre en minúsculas.

Por ejemplo, en private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Se convierte en lo siguiente:

  • Nombre descriptivo: sistema
  • uid: 1000
  • gid: 1000

Para agregar un nuevo AID principal de AOSP, simplemente agrega el #define al archivo de encabezado android_filesystem_config.h. El AID se genera en la compilación y se pone a disposición de las interfaces que usan argumentos de usuario y grupo. Las herramientas validan que el nuevo AID no esté dentro de los rangos de la app o del OEM. También respetan los cambios en esos rangos y deberían reconfigurarse automáticamente en los cambios o en los nuevos rangos reservados por el OEM.

Configurar AID

Para habilitar el nuevo mecanismo de AID, configura TARGET_FS_CONFIG_GEN en el archivo BoardConfig.mk. Esta variable contiene una lista de archivos de configuración, lo que te permite agregar archivos según sea necesario.

Por convención, los archivos de configuración usan el nombre config.fs, pero, en la práctica, puedes usar cualquier nombre. Los archivos config.fs están en el formato INI de ConfigParser de Python y, además, incluyen una sección de mayúsculas (para configurar las capacidades del sistema de archivos) y una sección de AIDs (para configurar los AIDs de OEM).

Configura la sección de mayúsculas

La sección de mayúsculas admite la configuración de funciones del sistema de archivos en objetos del sistema de archivos dentro de la compilación (el sistema de archivos también debe admitir esta funcionalidad).

Debido a que ejecutar un servicio estable como root en Android causa una falla del Conjunto de pruebas de compatibilidad (CTS), los requisitos anteriores para retener una capability mientras se ejecutaba un proceso o servicio implicaban configurar capabilities y, luego, usar setuid/setgid en un AID adecuado para ejecutarlo. Con las mayúsculas, puedes omitir estos requisitos y hacer que el kernel lo haga por ti. Cuando se entrega el control a main(), tu proceso ya tiene las capacidades que necesita para que tu servicio pueda usar un usuario y un grupo que no sean raíz (esta es la forma preferida de iniciar servicios con privilegios).

La sección de mayúsculas usa la siguiente sintaxis:

Sección Valor Definición
[path] La ruta del sistema de archivos que se configurará. Una ruta de acceso que termina en / se considera un directorio, de lo contrario, es un archivo.

Es un error especificar varias secciones con el mismo [path] en diferentes archivos. En las versiones de Python anteriores o iguales a 3.2, el mismo archivo puede contener secciones que anulan la sección anterior. En Python 3.2, se establece en modo estricto.
mode Modo de archivo octal Un modo de archivo octal válido de al menos 3 dígitos. Si se especifica 3, se le agrega un prefijo 0; de lo contrario, se usa el modo tal como está.
user AID_<usuario> El define de C para un AID válido o el nombre descriptivo (p. ej., se aceptan AID_RADIO y radio) Para definir un AID personalizado, consulta la sección Configuración de AID.
group AID_<grupo> Igual que el usuario.
caps cap* Es el nombre como se declara en bionic/libc/kernel/uapi/linux/capability.h sin el CAP_ inicial. Se permite la combinación de mayúsculas y minúsculas. Las mayúsculas también pueden ser las siguientes:
  • binario (0b0101)
  • octal (0455)
  • int (42)
  • hexadecimal (0xFF)
Separa las mayúsculas con espacios en blanco.

Para ver un ejemplo de uso, consulta Cómo usar las funciones del sistema de archivos.

Configura la sección de AID

La sección de AID contiene AID de OEM y usa la siguiente sintaxis:

Sección Valor Definición
[AID_<name>] El <name> puede contener caracteres del conjunto de letras en mayúsculas, números y guiones bajos. La versión en minúsculas es el nombre descriptivo. El archivo de encabezado generado para incluir código usa el AID_<name> exacto.

Es un error especificar varias secciones con el mismo AID_<name> (sin distinción entre mayúsculas y minúsculas con las mismas restricciones que [path]).

<name> debe comenzar con un nombre de partición para garantizar que no entre en conflicto con diferentes fuentes.
value <número> Es una cadena numérica válida de estilo C (hexadecimal, octal, binario y decimal).

Es un error especificar varias secciones con la misma opción de valor.

Las opciones de valor se deben especificar en el rango correspondiente a la partición que se usa en <name>. La lista de particiones válidas y sus rangos correspondientes se define en system/core/libcutils/include/private/android_filesystem_config.h. Las opciones son las siguientes:
  • Partición del proveedor
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • Partición del sistema
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • Partición de ODM
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • Partición de producto
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • Partición system_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

Para ver ejemplos de uso, consulta Cómo definir nombres de AID de OEM y Cómo usar AID de OEM.

Ejemplos de uso

En los siguientes ejemplos, se detalla cómo definir y usar un AID de OEM y cómo habilitar las funciones del sistema de archivos. Los nombres de AID del OEM ([AID_name]) deben comenzar con un nombre de partición, como "vendor_", para garantizar que no entren en conflicto con nombres futuros de AOSP ni con otras particiones.

Define los nombres de los AIDs de OEM

Para definir un AID de OEM, crea un archivo config.fs y establece el valor de AID. Por ejemplo, en device/x/y/config.fs, configura lo siguiente:

[AID_VENDOR_FOO]
value: 2900

Después de crear el archivo, configura la variable TARGET_FS_CONFIG_GEN y apúntala en BoardConfig.mk. Por ejemplo, en device/x/y/BoardConfig.mk, configura lo siguiente:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

El sistema ahora puede consumir tu AID personalizado en una compilación nueva.

Usa AIDs de OEM

Para usar un AID de OEM, en tu código C, incluye oemaids_headers en el Makefile asociado y agrega #include "generated_oem_aid.h". Luego, comienza a usar los identificadores declarados. Por ejemplo, en my_file.c, agrega lo siguiente:

#include "generated_oem_aid.h"


If (ipc->uid == AID_VENDOR_FOO) {
  // Do something
...

En el archivo Android.bp asociado, agrega lo siguiente:

header_libs: ["oemaids_headers"],

Si usas un archivo Android.mk, agrega lo siguiente:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Usa nombres descriptivos

En Android 9, puedes usar el nombre amigable para cualquier interfaz que admita nombres de AID. Por ejemplo:

  • En un comando chown en some/init.rc:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • En un service en some/init.rc:
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

Debido a que /vendor/etc/passwd y /vendor/etc/group realizan la asignación interna del nombre descriptivo al UID, se debe activar la partición del proveedor.

Asocia nombres descriptivos

Android 9 admite la asociación de un nombre descriptivo con el valor real de AID del OEM. Puedes usar argumentos de cadena no numéricos para el usuario y el grupo, es decir, "vendor_foo" en lugar de "2901".

Conversión de AID a nombres fáciles de entender

Para los AID de OEM, Android 8.x requería el uso de oem_#### con getpwnam y funciones similares, además de lugares que controlan búsquedas con getpwnam (como secuencias de comandos init). En Android 9, puedes usar los amigos getpwnam y getgrnam en Bionic para convertir de IDs de Android (AID) a nombres amigables y viceversa.

Usa las funciones del sistema de archivos

Para habilitar las funciones del sistema de archivos, crea una sección de mayúsculas en el archivo config.fs. Por ejemplo, en device/x/y/config.fs, agrega la siguiente sección:

[system/bin/foo_service]
mode: 0555
user: AID_VENDOR_FOO
group: AID_SYSTEM
caps: SYS_ADMIN | SYS_NICE

Después de crear el archivo, configura TARGET_FS_CONFIG_GEN para que apunte a ese archivo en BoardConfig.mk. Por ejemplo, en device/x/y/BoardConfig.mk, configura lo siguiente:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

Cuando se ejecuta el servicio vendor_foo, comienza con las capacidades CAP_SYS_ADMIN y CAP_SYS_NICE sin llamadas a setuid ni setgid. Además, la política de SELinux del servicio vendor_foo ya no necesita las capacidades setuid y setgid, y se puede borrar.

Configura anulaciones (Android 6.x-7.x)

Android 6.0 reubicó fs_config y las definiciones de estructura asociadas (system/core/include/private/android_filesystem_config.h) a system/core/libcutils/fs_config.c, donde se podían actualizar o anular con archivos binarios instalados en /system/etc/fs_config_dirs y /system/etc/fs_config_files. El uso de reglas de coincidencia y análisis separadas para directorios y archivos (que podrían usar expresiones glob adicionales) permitió que Android controlara directorios y archivos en dos tablas diferentes. Las definiciones de estructura en system/core/libcutils/fs_config.c no solo permitían la lectura del entorno de ejecución de directorios y archivos, sino que el host podía usar los mismos archivos durante el tiempo de compilación para crear imágenes del sistema de archivos como ${OUT}/system/etc/fs_config_dirs y ${OUT}/system/etc/fs_config_files.

Si bien el método de anulación para extender el sistema de archivos se reemplazó por el sistema de configuración modular que se introdujo en Android 8.0, puedes seguir usando el método anterior si lo deseas. En las siguientes secciones, se detalla cómo generar e incluir archivos de anulación y configurar el sistema de archivos.

Genera archivos de anulación

Puedes generar los archivos binarios alineados /system/etc/fs_config_dirs y /system/etc/fs_config_files con la herramienta fs_config_generate en build/tools/fs_config. La herramienta usa una función de biblioteca libcutils (fs_config_generate()) para administrar los requisitos de DAC en un búfer y define reglas para un archivo de inclusión para institucionalizar las reglas de DAC.

Para usarlo, crea un archivo de inclusión en device/vendor/device/android_filesystem_config.h que actúe como la anulación. El archivo debe usar el formato structure fs_path_config definido en system/core/include/private/android_filesystem_config.h con las siguientes inicializaciones de estructura para los símbolos de directorio y archivo:

  • Para los directorios, usa android_device_dirs[].
  • Para los archivos, usa android_device_files[].

Cuando no usas android_device_dirs[] ni android_device_files[], puedes definir NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS y NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (consulta el ejemplo a continuación). También puedes especificar el archivo de anulación con TARGET_ANDROID_FILESYSTEM_CONFIG_H en la configuración de la placa, con un nombre de base obligatorio de android_filesystem_config.h.

Cómo incluir archivos de anulación

Para incluir archivos, asegúrate de que PRODUCT_PACKAGES incluya fs_config_dirs o fs_config_files para que pueda instalarlos en /system/etc/fs_config_dirs y /system/etc/fs_config_files, respectivamente. El sistema de compilación busca android_filesystem_config.h personalizados en $(TARGET_DEVICE_DIR), donde existe BoardConfig.mk. Si este archivo existe en otro lugar, establece la variable de configuración de la placa TARGET_ANDROID_FILESYSTEM_CONFIG_H para que apunte a esa ubicación.

Configura el sistema de archivos

Para configurar el sistema de archivos en Android 6.0 y versiones posteriores, haz lo siguiente:

  1. Crea el archivo $(TARGET_DEVICE_DIR)/android_filesystem_config.h.
  2. Agrega fs_config_dirs o fs_config_files a PRODUCT_PACKAGES en el archivo de configuración de la placa (p.ej., $(TARGET_DEVICE_DIR)/device.mk).

Ejemplo de anulación

En este ejemplo, se muestra un parche para anular el daemon system/bin/glgps y agregar compatibilidad con el bloqueo de activación en el directorio device/vendor/device. Ten en cuenta lo siguiente:

  • Cada entrada de la estructura es el modo, el UID, el GID, las capacidades y el nombre. system/core/include/private/android_filesystem_config.h se incluye automáticamente para proporcionar el manifiesto #define (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • La sección android_device_files[] incluye una acción para suprimir el acceso a system/etc/fs_config_dirs cuando no se especifica, que sirve como protección DAC adicional por falta de contenido para las anulaciones de directorio. Sin embargo, esta es una protección débil. Si alguien tiene control sobre /system, por lo general, puede hacer lo que quiera.
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)

Cómo migrar sistemas de archivos desde versiones anteriores

Cuando migres sistemas de archivos de Android 5.x y versiones anteriores, ten en cuenta que Android 6.x

  • Quita algunas incorporaciones, estructuras y definiciones intercaladas.
  • Requiere una referencia a libcutils en lugar de ejecutarse directamente desde system/core/include/private/android_filesystem_config.h. Los ejecutables privados del fabricante del dispositivo que dependen de system/code/include/private_filesystem_config.h para las estructuras de archivos o directorios o fs_config deben agregar dependencias de bibliotecas libcutils.
  • Requiere copias de rama privada del fabricante del dispositivo de system/core/include/private/android_filesystem_config.h con contenido adicional en los destinos existentes para pasar a device/vendor/device/android_filesystem_config.h.
  • Se reserva el derecho de aplicar controles de acceso obligatorios (MAC) de SELinux a los archivos de configuración del sistema de destino. Las implementaciones que incluyen ejecutables de destino personalizados con fs_config() deben garantizar el acceso.