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

Les objets et services du système de fichiers ajoutés à la compilation ont souvent besoin d'ID uniques distincts, appelés ID Android (AID). Actuellement, de nombreuses ressources, telles que des fichiers et des services, utilisent inutilement des AID de base (définis par Android). 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) étendaient le mécanisme des AIDs à 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 ne permettait pas d'utiliser des noms descriptifs pour les AID OEM, vous deviez spécifier le nombre brut pour les champs utilisateur et groupe sans pouvoir associer un nom descriptif à l'AID numérique.

Les versions plus récentes d'Android (Android 8.0 et versions ultérieures) sont compatibles avec une nouvelle méthode d' extension des 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 des configurations de compilation extensibles ).
  • Vérification de l'intégrité des valeurs d'AID OEM au moment de la compilation.
  • Génération d'un en-tête d'AID OEM personnalisé pouvant être utilisé dans les fichiers sources si nécessaire.
  • Association d'un nom descriptif à la valeur réelle de l'AID OEM. Prise en charge des arguments de chaîne non numériques pour l'utilisateur et le groupe, par exemple "foo" au lieu de "2901".

Les améliorations supplémentaires incluent la suppression du android_ids[] tableau de system/core/libcutils/include/private/android_filesystem_config.h. 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, car les AID de base sont modifiés.) Pour obtenir des outils et un fichier README contenant plus d'informations, 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 descriptifs d'AID sont générés à partir du system/core/libcutils/include/private/android_filesystem_config.h fichier d'en-tête lors de la génération du tableau Bionic android_ids[]. Tout define correspondant à AID_* est récupéré par l'outil 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 nouvel AID de base AOSP, ajoutez simplement le #define au android_filesystem_config.h fichier d'en-tête. L'AID est généré lors de la compilation et mis à disposition des interfaces qui utilisent des arguments utilisateur et groupe. L'outil valide 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 aux OEM.

Configurer les AID

Pour activer le nouveau mécanisme d'AID, définissez TARGET_FS_CONFIG_GEN dans le BoardConfig.mk fichier. 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 ini Python ConfigParser et incluent une section "caps" (pour configurer les fonctionnalités du système de fichiers) et une section "AIDs" (pour configurer les AID OEM).

Configurer la section "caps"

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

Étant donné que l'exécution d'un service stable en tant que racine dans Android entraîne un échec de la Compatibility Test Suite (CTS) , les exigences précédentes pour conserver une fonctionnalité lors de l'exécution d'un processus ou d'un service impliquaient la configuration des fonctionnalités, puis l'utilisation de setuid/setgid sur un AID approprié pour l'exécution. Avec les fonctionnalités, vous pouvez ignorer ces exigences et laisser le noyau le faire pour vous. 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 (il s'agit de 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 du 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.

Une erreur se produit si vous spécifiez plusieurs sections avec le même [path] dans différents fichiers. Dans les versions de Python <= 3.2, le même fichier peut contenir des sections qui remplacent la section précédente. Dans Python 3.2, il est défini sur le mode strict.
mode Mode de fichier octal Mode de fichier octal valide d'au moins trois chiffres. 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 acceptables). Pour définir un AID personnalisé, consultez Configurer la section "AID".
group AID_<group> Identique à l'utilisateur.
caps cap* Nom tel qu'il est déclaré dans bionic/libc/kernel/uapi/linux/capability.h sans le CAP_ initial. Les majuscules et les minuscules sont autorisées. Les fonctionnalités peuvent également être brutes:
  • binaire (0b0101)
  • octal (0455)
  • int (42)
  • hex (0xFF)
Séparez plusieurs fonctionnalités à l'aide d'espaces.

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

Configurer la section "AID"

La section "AID" contient des AID OEM et utilise la syntaxe suivante :

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

Une erreur se produit si vous spécifiez plusieurs sections avec le même AID_<name> (sans tenir compte de 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 de nombre de style C valide (hexadécimal, octal, binaire et décimal).

Une erreur se produit si vous spécifiez 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 de leurs plages correspondantes est définie dans system/core/libcutils/include/private/android_filesystem_config.h. Vous disposez des options 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 de produit
    • 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 n'entrent pas en conflit avec les 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-la 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 sur une nouvelle compilation.

Utiliser des AID OEM

Pour utiliser un AID OEM, dans votre code C, incluez le oemaids_headers dans votre Makefile associé, 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 votre 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

Dans Android 9, vous pouvez utiliser le nom descriptif pour n'importe quelle 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 descriptif à l'uid est effectué par /vendor/etc/passwd et /vendor/etc/group, la partition du fournisseur doit être installée.

Associer des noms descriptifs

Android 9 permet d'associer un nom descriptif à 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 un 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 (tels que les scripts init). Dans Android 9, vous pouvez utiliser les amis getpwnam et getgrnam dans Bionic pour convertir des ID Android (AID) en noms descriptifs 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 "caps" dans le config.fs fichier. 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 le 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. De plus, la stratégie SELinux du service vendor_foo n'a plus besoin des fonctionnalités setuid et setgid, et peut être supprimée.

Configurer les remplacements (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ù ils pouvaient être mis à jour ou remplacés 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 pouvaient 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 au moment de l'exécution des répertoires et des fichiers, mais l'hôte pouvait utiliser les mêmes fichiers au moment de la compilation pour construire des images du système de fichiers en tant que ${OUT}/system/etc/fs_config_dirs et ${OUT}/system/etc/fs_config_files.

Bien que la méthode de remplacement d'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 des règles pour un fichier d'inclusion afin d'institutionnaliser les règles DAC.

Pour l'utiliser, créez un fichier d'inclusion dans device/vendor/device/android_filesystem_config.h qui fait office 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[] et 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 remplacement à 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 des 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 respectivement dans /system/etc/fs_config_dirs et /system/etc/fs_config_files. Le système de compilation recherche un android_filesystem_config.h personnalisé 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 dans Android 6.0 et versions ultérieures :

  1. Créez le $(TARGET_DEVICE_DIR)/android_filesystem_config.h fichier.
  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 d'exception

Cet exemple montre un correctif permettant de remplacer le system/bin/glgps démon afin d'ajouter la prise en charge du wakelock dans le device/vendor/device répertoire. Gardez à l’esprit ce qui suit :

  • Chaque entrée de 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 #defines du fichier manifeste (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • La section android_device_files[] inclut une action permettant de supprimer l'accès à system/etc/fs_config_dirs lorsqu'elle n'est pas spécifiée, ce qui sert de protection DAC supplémentaire en cas de manque de contenu pour les remplacements de répertoire. Toutefois, il s'agit d'une protection 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, n'oubliez pas qu' Android 6.x

  • supprime certaines inclusions, structures et définitions intégrées ;
  • nécessite une référence à libcutils au lieu d’une exécution directe à 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 fs_config doivent ajouter des dépendances de bibliothèque libcutils.
  • nécessite des copies de branche privées du fabricant de l'appareil de system/core/include/private/android_filesystem_config.h avec du contenu supplémentaire sur les cibles existantes à déplacer vers device/vendor/device/android_filesystem_config.h.
  • se réserve le droit d'appliquer des 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 garantir l'accès.