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 et distincts, appelés ID Android (AID). Actuellement, de nombreuses ressources telles que les fichiers et les services utilisent inutilement des AID principaux (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 AID à l'aide d'un fichier android_filesystem_config.h spécifique à l'appareil pour spécifier les capacité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 conviviaux pour les AID OEM. Il vous obligeait à spécifier le nombre brut pour les champs utilisateur et groupe, sans moyen d'associer un nom convivial à 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 capacité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 (permettent des configurations de compilation extensibles).
  • Vérification de cohérence au moment de la compilation des valeurs AID de l'OEM.
  • Génération d'un en-tête AID OEM personnalisé pouvant être utilisé dans les fichiers sources si nécessaire.
  • Association d'un nom convivial à la valeur AID OEM réelle. Accepte les arguments de chaîne non numériques pour l'utilisateur et le groupe, c'est-à-dire "foo" au lieu de "2901".

Les autres améliorations incluent la suppression du tableau android_ids[] 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 lorsque les AID principaux 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 compatibles avec 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 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 AOSP, il vous suffit d'ajouter #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 d'utilisateur et de 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 devrait 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 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 ini Python ConfigParser et incluent une section "caps" (pour configurer les capacités du système de fichiers) et une section "AIDs" (pour configurer les AID OEM).

Configurer la section "Plafonds"

La section "caps" permet de définir les capacité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 prendre en charge cette fonctionnalité).

Étant donné que l'exécution d'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 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 pour exécuter un AID approprié. Avec les capacités, vous pouvez ignorer ces exigences et laisser le noyau s'en charger pour vous. Lorsque le contrôle est transmis à main(), votre processus dispose déjà des capacité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 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 Python 3.2 et antérieures, 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 fichier octal Mode de fichier octal valide d'au moins trois chiffres. Si la valeur 3 est spécifiée, elle est précédée d'un 0. Sinon, le mode est utilisé tel quel.
user AID_<user> Il peut s'agir du C define pour un AID valide ou du nom convivial (par exemple, AID_RADIO et radio sont acceptables). Pour définir un AID personnalisé, consultez la section Configurer l'AID.
group AID_<group> Identique à celui de 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 majuscules peuvent également être brutes :
  • binaire (0b0101)
  • octal (0455)
  • int (42)
  • hex (0xFF)
Séparez les plafonds multiples par des 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 les 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 convivial. Le fichier d'en-tête généré pour l'inclusion de code utilise exactement 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 éviter tout conflit avec différentes sources.
value <number> 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 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 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 les futurs noms AOSP ou d'autres partitions.

Définir les noms des AID OEM

Pour définir un AID OEM, créez un fichier config.fs et définissez la valeur 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 dessus 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 version.

Utiliser les AID OEM

Pour utiliser un AID OEM, dans votre code C, incluez oemaids_headers dans votre fichier Makefile associé, puis ajoutez #include "generated_oem_aid.h". Vous pouvez ensuite commencer à 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 lignes suivantes :

LOCAL_HEADER_LIBRARIES := oemaids_headers

Utiliser des noms conviviaux

Dans Android 9, vous pouvez utiliser le nom convivial pour n'importe quelle interface compatible avec les noms AID. Exemple :

  • Dans une commande chown dans some/init.rc :
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • Dans un service de 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 AID OEM réelle. 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 conviviaux

Pour les AIDs OEM, Android 8.x exigeait l'utilisation de oem_#### avec getpwnam et des fonctions similaires, ainsi que dans les endroits 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 "caps" 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 capacités CAP_SYS_ADMIN et CAP_SYS_NICE sans les appels setuid et setgid. De plus, la stratégie SELinux du service vendor_foo n'a plus besoin des capacité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ù elles peuvent ê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 d'analyse et de correspondance distinctes pour les répertoires et les fichiers (qui pourraient 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 des répertoires et des fichiers au moment de l'exécution, mais l'hôte pouvait également utiliser les mêmes fichiers au moment de la compilation pour construire 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 remplacement pour étendre le 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 en détail 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 sert 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 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és 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 désigne 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 pour remplacer le démon system/bin/glgps afin d'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 structure correspond au mode, à l'UID, au GID, aux capacité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 permettant de supprimer l'accès à system/etc/fs_config_dirs lorsque cela n'est pas spécifié. Cela sert de protection DAC supplémentaire en cas d'absence de contenu pour les remplacements de répertoire. Toutefois, il s'agit d'une protection faible. Si quelqu'un a le contrôle sur /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 depuis Android 5.x ou une version antérieure, gardez à l'esprit qu'Android 6.x

  • Supprime certaines inclusions, structures et définitions intégrées.
  • Nécessite une référence à libcutils au lieu d'être exécuté 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 system/core/include/private/android_filesystem_config.h avec du contenu supplémentaire sur les cibles existantes pour passer à device/vendor/device/android_filesystem_config.h.
  • Se réserve le droit d'appliquer des contrôles d'accès obligatoires SELinux (MAC) 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.