Contrôle des accès discrétionnaire (DAC)

Les objets et services du système de fichiers ajoutés au build ont souvent besoin d'ID uniques distincts, appelés ID Android (AID). Actuellement, de nombreuses ressources telles que les fichiers et les services utilisent des AID de base (définis par Android) inutilement. Dans de nombreux cas, vous pouvez utiliser des AID OEM (définis par l'OEM) à la place.

Les versions antérieures d'Android (Android 7.x et versions antérieures) ont étendu le mécanisme des AID à l'aide d'un fichier android_filesystem_config.h spécifique à l'appareil pour spécifier les fonctionnalités du système de fichiers et/ou les AID OEM personnalisés. Toutefois, ce système n'était pas intuitif, car il n'était pas possible d'utiliser des noms conviviaux pour les AID OEM. Vous deviez donc spécifier le nombre brut pour les champs utilisateur et de groupe, sans pouvoir associer un nom convivial à l'AID numérique.

Les versions plus récentes d'Android (Android 8.0 et versions ultérieures) prennent en charge une nouvelle méthode pour étendre les fonctionnalités du système de fichiers. Cette nouvelle méthode est compatible avec les éléments suivants:

  • Plusieurs emplacements sources pour les fichiers de configuration (permet d'étendre les configurations de compilation).
  • Vérification de la validité des valeurs de l'AID OEM au moment de la compilation.
  • Génération d'un en-tête OEM AID personnalisé pouvant être utilisé dans les fichiers sources si nécessaire.
  • Association d'un nom descriptif à la valeur réelle de l'AID OEM. Prend en charge les arguments de chaîne non numériques pour l'utilisateur et le groupe, c'est-à-dire "foo" au lieu de "2901".

Parmi les autres améliorations, la suppression du tableau android_ids[] de system/core/libcutils/include/private/android_filesystem_config.h est à noter. Ce tableau existe désormais dans Bionic en tant que tableau généré entièrement privé, avec des accesseurs avec getpwnam() et getgrnam(). (Cela a pour effet secondaire de produire des binaires stables à mesure que les AID principaux sont modifiés.) Pour en savoir plus sur les outils et le fichier README, consultez build/make/tools/fs_config.

Ajouter des ID Android (AID)

Android 8.0 a supprimé le tableau android_ids[] du projet Android Open Source (AOSP). Tous les noms compatibles avec l'AID sont générés à partir du fichier d'en-tête system/core/libcutils/include/private/android_filesystem_config.h lors de la génération du tableau android_ids[] Bionic. Tout define correspondant à AID_* est détecté par les outils et * devient le nom en minuscules.

Par exemple, dans private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Devient:

  • Nom descriptif: système
  • uid: 1000
  • gid: 1000

Pour ajouter un AID principal AOSP, ajoutez simplement #define au fichier d'en-tête android_filesystem_config.h. L'AID est généré lors de la compilation et mis à la disposition des interfaces qui utilisent des arguments utilisateur et de groupe. L'outil vérifie que le nouvel AID ne se trouve pas dans les plages APP ou OEM. Il respecte également les modifications apportées à ces plages et doit se reconfigurer automatiquement en cas de modification ou de nouvelles plages réservées à l'OEM.

Configurer les AID

Pour activer le nouveau mécanisme d'AID, définissez TARGET_FS_CONFIG_GEN dans le fichier BoardConfig.mk. Cette variable contient une liste de fichiers de configuration, ce qui vous permet d'ajouter des fichiers si nécessaire.

Par convention, les fichiers de configuration utilisent le nom config.fs, mais en pratique, vous pouvez utiliser n'importe quel nom. Les fichiers config.fs sont au format ININ ConfigParser de Python et incluent une section en majuscules (pour configurer les fonctionnalités du système de fichiers) et une section AID (pour configurer les AID OEM).

Configurer la section "Casquettes"

La section des majuscules permet de définir les fonctionnalités du système de fichiers sur les objets de système de fichiers de la compilation (le système de fichiers lui-même doit également être compatible avec cette fonctionnalité).

Étant donné qu'exécuter un service stable en tant que root dans Android entraîne un échec de la Compatibility Test Suite (CTS), les exigences précédentes pour conserver une capacité lors de l'exécution d'un processus ou d'un service impliquaient de configurer des fonctionnalités, puis d'utiliser setuid/setgid pour un AID approprié à exécuter. Avec les bouchons, vous pouvez ignorer ces exigences et laisser le noyau s'en charger. Lorsque le contrôle est transmis à main(), votre processus dispose déjà des fonctionnalités dont il a besoin pour que votre service puisse utiliser un utilisateur et un groupe non racine (c'est la méthode privilégiée pour démarrer des services privilégiés).

La section "Caps" utilise la syntaxe suivante:

Section Valeur Définition
[path] Chemin d'accès au système de fichiers à configurer. Un chemin d'accès se terminant par / est considéré comme un répertoire, sinon il s'agit d'un fichier.

Il est erroné de spécifier plusieurs sections avec le même [path] dans différents fichiers. Dans les versions 3.2 et ultérieures de Python, le même fichier peut contenir des sections qui remplacent la section précédente. Dans Python 3.2, il est défini en mode strict.
mode Mode de fichier octal Un mode de fichier octal valide de trois chiffres minimum. Si 3 est spécifié, il est précédé d'un 0, sinon le mode est utilisé tel quel.
user AID_<user> Soit le C define pour un AID valide, soit le nom descriptif (par exemple, AID_RADIO et radio sont acceptés). Pour définir un AID personnalisé, consultez la section Configurer la section AID.
group AID_<groupe> Identique à celui de l'utilisateur.
caps casquette* Nom tel que déclaré dans bionic/libc/kernel/uapi/linux/capability.h, sans le CAP_ initial. Majuscules et minuscules autorisés. Les casquettes peuvent également être brutes :
  • binaire (0b0101)
  • octal (0455)
  • int (42)
  • hexadécimal (0xFF)
Séparez les majuscules à l'aide d'espaces blancs.

Pour obtenir un exemple d'utilisation, consultez la section Utiliser les fonctionnalités du système de fichiers.

Configurer la section AID

La section AID contient les AID OEM et utilise la syntaxe suivante:

Section Valeur Définition
[AID_<name>] Le <name> peut contenir des caractères de l'ensemble en majuscules, des chiffres et des traits de soulignement. La version en minuscules est utilisée comme nom convivial. Le fichier d'en-tête généré pour l'inclusion de code utilise exactement le AID_<name>.

Il est impossible de spécifier plusieurs sections avec le même AID_<name> (insensible à la casse, avec les mêmes contraintes que [path]).

<name> doit commencer par un nom de partition pour s'assurer qu'il n'entre pas en conflit avec différentes sources.
value <nombre> Chaîne numérique de style C valide (hexadécimal, octale, binaire et décimal).

Il s'agit d'une erreur de spécifier plusieurs sections avec la même option de valeur.

Les options de valeur doivent être spécifiées dans la plage correspondant à la partition utilisée dans <name>. La liste des partitions valides et des plages correspondantes est définie dans system/core/libcutils/include/private/android_filesystem_config.h. Les options sont les suivantes :
  • Partition du fournisseur
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • Partition système
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • Partition ODM
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • Partition des produits
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • Partition System_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

Pour obtenir des exemples d'utilisation, consultez Définir des noms d'AID OEM et Utiliser des AID OEM.

Exemples d'utilisation

Les exemples suivants expliquent comment définir et utiliser un AID OEM, et comment activer les fonctionnalités du système de fichiers. Les noms d'AID OEM ([AID_name]) doivent commencer par un nom de partition tel que "vendor_" pour s'assurer qu'ils ne sont pas en conflit avec de futurs noms AOSP ou d'autres partitions.

Définir des noms d'AID OEM

Pour définir un AID OEM, créez un fichier config.fs et définissez la valeur de l'AID. Par exemple, dans device/x/y/config.fs, définissez les éléments suivants:

[AID_VENDOR_FOO]
value: 2900

Après avoir créé le fichier, définissez la variable TARGET_FS_CONFIG_GEN et pointez-y dans BoardConfig.mk. Par exemple, dans device/x/y/BoardConfig.mk, définissez les éléments suivants:

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

Votre AID personnalisé peut désormais être utilisé par le système dans son ensemble lors d'une nouvelle compilation.

Utiliser des AID OEM

Pour utiliser un AID OEM, dans votre code C, incluez oemaids_headers dans votre Makefile associé, puis ajoutez #include "generated_oem_aid.h", puis commencez à utiliser les identifiants déclarés. Par exemple, dans my_file.c, ajoutez les éléments suivants:

#include "generated_oem_aid.h"


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

Dans le fichier Android.bp associé, ajoutez les éléments suivants:

header_libs: ["oemaids_headers"],

Si vous utilisez un fichier Android.mk, ajoutez les éléments suivants:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Utiliser des noms descriptifs

Sous Android 9, vous pouvez utiliser le nom convivial de toute interface compatible avec les noms d'AID. Exemple :

  • Dans une commande chown dans some/init.rc:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • Dans un service dans some/init.rc:
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

Étant donné que le mappage interne du nom convivial à l'UID est effectué par /vendor/etc/passwd et /vendor/etc/group, la partition du fournisseur doit être montée.

Associer des noms descriptifs

Android 9 permet d'associer un nom convivial à la valeur réelle de l'AID OEM. Vous pouvez utiliser des arguments de chaîne non numériques pour l'utilisateur et le groupe, c'est-à-dire "vendor_foo" au lieu de "2901".

Convertir les AID en noms descriptifs

Pour les AID OEM, Android 8.x nécessitait l'utilisation de oem_#### avec getpwnam et des fonctions similaires, ainsi que dans les emplacements qui gèrent les recherches avec getpwnam (comme les scripts init). Dans Android 9, vous pouvez utiliser les amis getpwnam et getgrnam dans Bionic pour convertir les ID Android (AID) en noms conviviaux, et inversement.

Utiliser les fonctionnalités du système de fichiers

Pour activer les fonctionnalités du système de fichiers, créez une section de majuscules dans le fichier config.fs. Par exemple, dans device/x/y/config.fs, ajoutez la section suivante:

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

Après avoir créé le fichier, définissez TARGET_FS_CONFIG_GEN pour qu'il pointe vers ce fichier dans BoardConfig.mk. Par exemple, dans device/x/y/BoardConfig.mk, définissez les éléments suivants:

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

Lorsque le service vendor_foo est exécuté, il démarre avec les fonctionnalités CAP_SYS_ADMIN et CAP_SYS_NICE sans appels setuid et setgid. En outre, la règle SELinux du service vendor_foo n'a plus besoin des capacités setuid et setgid et peut être supprimée.

Configurer les forçages (Android 6.x à 7.x)

Android 6.0 a déplacé fs_config et les définitions de structure associées (system/core/include/private/android_filesystem_config.h) vers system/core/libcutils/fs_config.c, où elles pourraient être mises à jour ou remplacées par des fichiers binaires installés dans /system/etc/fs_config_dirs et /system/etc/fs_config_files. L'utilisation de règles de correspondance et d'analyse distinctes pour les répertoires et les fichiers (qui peuvent utiliser des expressions glob supplémentaires) a permis à Android de gérer les répertoires et les fichiers dans deux tables différentes. Les définitions de structure dans system/core/libcutils/fs_config.c permettaient non seulement la lecture d'exécution des répertoires et des fichiers, mais l'hôte pouvait également utiliser les mêmes fichiers au moment de la compilation pour créer des images de système de fichiers comme ${OUT}/system/etc/fs_config_dirs et ${OUT}/system/etc/fs_config_files.

Bien que la méthode de forçage de l'extension du système de fichiers ait été remplacée par le système de configuration modulaire introduit dans Android 8.0, vous pouvez toujours utiliser l'ancienne méthode si vous le souhaitez. Les sections suivantes expliquent comment générer et inclure des fichiers de remplacement, et comment configurer le système de fichiers.

Générer des fichiers de remplacement

Vous pouvez générer les fichiers binaires alignés /system/etc/fs_config_dirs et /system/etc/fs_config_files à l'aide de l'outil fs_config_generate dans build/tools/fs_config. L'outil utilise une fonction de bibliothèque libcutils (fs_config_generate()) pour gérer les exigences DAC dans un tampon et définit les règles d'un fichier d'inclusion afin d'institutionnaliser ces règles.

Pour l'utiliser, créez un fichier d'inclusion dans device/vendor/device/android_filesystem_config.h qui servira de remplacement. Le fichier doit utiliser le format structure fs_path_config défini dans system/core/include/private/android_filesystem_config.h avec les initialisations de structure suivantes pour les symboles de répertoire et de fichier:

  • Pour les répertoires, utilisez android_device_dirs[].
  • Pour les fichiers, utilisez android_device_files[].

Lorsque vous n'utilisez pas android_device_dirs[] ni android_device_files[], vous pouvez définir NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS et NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (voir l'exemple ci-dessous). Vous pouvez également spécifier le fichier de forçage à l'aide de TARGET_ANDROID_FILESYSTEM_CONFIG_H dans la configuration de la carte, avec un nom de base forcé de android_filesystem_config.h.

Inclure les fichiers de remplacement

Pour inclure des fichiers, assurez-vous que PRODUCT_PACKAGES inclut fs_config_dirs et/ou fs_config_files afin qu'il puisse les installer dans /system/etc/fs_config_dirs et /system/etc/fs_config_files, respectivement. Le système de compilation recherche les android_filesystem_config.h personnalisées dans $(TARGET_DEVICE_DIR), où BoardConfig.mk existe. Si ce fichier existe ailleurs, définissez la variable de configuration de la carte TARGET_ANDROID_FILESYSTEM_CONFIG_H pour qu'elle pointe vers cet emplacement.

Configurer le système de fichiers

Pour configurer le système de fichiers sous Android 6.0 ou version ultérieure:

  1. Créez le fichier $(TARGET_DEVICE_DIR)/android_filesystem_config.h.
  2. Ajoutez fs_config_dirs et/ou fs_config_files à PRODUCT_PACKAGES dans le fichier de configuration de la carte (par exemple, $(TARGET_DEVICE_DIR)/device.mk).

Exemple de remplacement

Cet exemple montre un correctif permettant de remplacer le daemon system/bin/glgps pour ajouter la prise en charge du verrouillage de réveil dans le répertoire device/vendor/device. Gardez à l'esprit les points suivants:

  • Chaque entrée de la structure correspond au mode, à l'UID, au gid, aux fonctionnalités et au nom. system/core/include/private/android_filesystem_config.h est inclus automatiquement pour fournir les définitions #du fichier manifeste (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • La section android_device_files[] inclut une action visant à supprimer l'accès à system/etc/fs_config_dirs lorsqu'il n'est pas spécifié, ce qui sert de protection DAC supplémentaire en cas d'absence de contenu pour les forçages de répertoire. Cependant, cette protection est faible. Si quelqu'un contrôle /system, il peut généralement faire ce qu'il veut.
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)

Migrer des systèmes de fichiers à partir de versions antérieures

Lorsque vous migrez des systèmes de fichiers à partir d'Android 5.x et versions antérieures, gardez à l'esprit que :

  • Supprime certaines inclusions, structures et définitions intégrées.
  • Nécessite une référence à libcutils au lieu de s'exécuter directement à partir de system/core/include/private/android_filesystem_config.h. Les exécutables privés du fabricant de l'appareil qui dépendent de system/code/include/private_filesystem_config.h pour les structures de fichiers ou de répertoires ou de fs_config doivent ajouter des dépendances de bibliothèque libcutils.
  • Nécessite des copies de branche privée du fabricant de l'appareil de la system/core/include/private/android_filesystem_config.h avec du contenu supplémentaire sur les cibles existantes à déplacer vers la device/vendor/device/android_filesystem_config.h.
  • Se réserve le droit d'appliquer les contrôles d'accès obligatoires (MAC) SELinux aux fichiers de configuration sur le système cible. Les implémentations qui incluent des exécutables cibles personnalisés à l'aide de fs_config() doivent assurer l'accès.