Personnalisation de SELinux

Après avoir intégré le niveau de base de la fonctionnalité SELinux et analysé en profondeur les résultats, vous pouvez ajouter vos propres paramètres de stratégie pour couvrir vos personnalisations du système d'exploitation Android. Ces stratégies doivent toujours répondre aux exigences du programme de compatibilité Android et ne doivent pas supprimer les paramètres SELinux par défaut.

Les fabricants ne doivent pas supprimer la politique SELinux existante. Sinon, ils risquent de casser l'implémentation Android SELinux et les applications qu'elle régit. Cela inclut les applications tierces qui devront probablement être améliorées pour être conformes et opérationnelles. Les applications ne doivent nécessiter aucune modification pour continuer à fonctionner sur les appareils compatibles SELinux.

Lorsque vous vous lancez dans la personnalisation de SELinux, n'oubliez pas de :

  • Écrire la politique SELinux pour tous les nouveaux démons
  • Utilisez des domaines prédéfinis chaque fois que nécessaire
  • Attribuez un domaine à tout processus généré en tant que service d' init
  • Se familiariser avec les macros avant d'écrire la politique
  • Soumettre les modifications apportées à la politique de base à l'AOSP

Et rappelez-vous de ne pas :

  • Créer une politique incompatible
  • Autoriser la personnalisation de la politique de l'utilisateur final
  • Autoriser les personnalisations de politique MDM
  • Faire peur aux utilisateurs en cas de non-respect des règles
  • Ajouter des portes dérobées

Consultez la section Fonctionnalités de sécurité du noyau du document Définition de compatibilité Android pour connaître les exigences spécifiques.

SELinux utilise une approche de liste blanche, ce qui signifie que tous les accès doivent être explicitement autorisés dans la politique pour être accordés. Étant donné que la politique SELinux par défaut d'Android prend déjà en charge le projet Open Source Android, vous n'êtes en aucun cas obligé de modifier les paramètres SELinux. Si vous personnalisez les paramètres SELinux, veillez à ne pas casser les applications existantes. Pour commencer:

  1. Utilisez le dernier noyau Android .
  2. Adoptez le principe du moindre privilège .
  3. Adressez uniquement vos propres ajouts à Android. La stratégie par défaut fonctionne automatiquement avec la base de code du projet Open Source Android .
  4. Compartimentez les composants logiciels en modules qui effectuent des tâches singulières.
  5. Créez des politiques SELinux qui isolent ces tâches des fonctions non liées.
  6. Placez ces politiques dans des fichiers *.te (l'extension des fichiers sources de politiques SELinux) dans le répertoire /device/ manufacturer / device-name /sepolicy et utilisez les variables BOARD_SEPOLICY pour les inclure dans votre build.
  7. Rendez initialement les nouveaux domaines permissifs. Cela se fait en utilisant une déclaration permissive dans le fichier .te du domaine.
  8. Analysez les résultats et affinez vos définitions de domaine.
  9. Supprimez la déclaration permissive lorsqu'aucun autre refus n'apparaît dans les versions userdebug.

Après avoir intégré votre changement de politique SELinux, ajoutez une étape à votre workflow de développement pour garantir la compatibilité SELinux à l'avenir. Dans un processus de développement logiciel idéal, la politique SELinux ne change que lorsque le modèle logiciel change et non l'implémentation réelle.

Lorsque vous commencez à personnaliser SELinux, auditez d'abord vos ajouts à Android. Si vous avez ajouté un composant qui exécute une nouvelle fonction, assurez-vous que le composant respecte la politique de sécurité d'Android, ainsi que toute politique associée élaborée par l'OEM, avant d'activer le mode d'application.

Pour éviter des problèmes inutiles, il est préférable d'être trop large et trop compatible que trop restrictif et incompatible, ce qui entraîne des fonctions de l'appareil cassées. Inversement, si vos modifications profitent à d'autres, vous devez soumettre les modifications à la politique SELinux par défaut en tant que correctif . Si le correctif est appliqué à la politique de sécurité par défaut, vous n'aurez pas besoin d'apporter cette modification à chaque nouvelle version d'Android.

Exemples de déclarations de stratégie

SELinux est basé sur le langage informatique M4 et prend donc en charge une variété de macros pour gagner du temps.

Dans l'exemple suivant, tous les domaines ont un accès en lecture ou en écriture dans /dev/null et en lecture à partir de /dev/zero .

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

Cette même déclaration peut être écrite avec les macros SELinux *_file_perms (raccourci) :

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

Exemple de politique

Voici un exemple complet de stratégie pour DHCP, que nous examinons ci-dessous :

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

Décortiquons l'exemple :

Dans la première ligne, la déclaration de type, le démon DHCP hérite de la politique de sécurité de base ( domain ). D'après les exemples d'instructions précédents, DHCP peut lire et écrire dans /dev/null .

Dans la deuxième ligne, DHCP est identifié comme un domaine permissif.

Dans la init_daemon_domain(dhcp) , la politique indique que DHCP est généré à partir d' init et est autorisé à communiquer avec lui.

Dans la net_domain(dhcp) , la stratégie permet à DHCP d'utiliser les fonctionnalités réseau communes du domaine net telles que la lecture et l'écriture de paquets TCP, la communication via des sockets et la conduite de requêtes DNS.

Dans la ligne allow dhcp proc_net:file write; , la politique stipule que DHCP peut écrire dans des fichiers spécifiques dans /proc . Cette ligne illustre l'étiquetage fin des fichiers de SELinux. Il utilise l'étiquette proc_net pour limiter l'accès en écriture aux seuls fichiers sous /proc/sys/net .

Le dernier bloc de l'exemple commençant par allow dhcp netd:fd use; décrit comment les applications peuvent être autorisées à interagir les unes avec les autres. La politique indique que DHCP et netd peuvent communiquer entre eux via des descripteurs de fichiers, des fichiers FIFO, des sockets de datagramme et des sockets de flux UNIX. DHCP peut uniquement lire et écrire à partir des sockets de datagramme et des sockets de flux UNIX et ne pas les créer ou les ouvrir.

Commandes disponibles

Classer Autorisation
fichier
ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
annuaire
add_name remove_name reparent search rmdir open audit_access execmod
prise
ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
système de fichiers
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
traiter
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
Sécurité
compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
aptitude
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

SUITE

ET PLUS

ne jamais autoriser les règles

Les règles SELinux neverallow interdisent un comportement qui ne devrait jamais se produire. Grâce aux tests de compatibilité , les règles neverallow de SELinux sont désormais appliquées sur tous les appareils.

Les directives suivantes sont destinées à aider les fabricants à éviter les erreurs liées aux règles neverallow lors de la personnalisation. Les numéros de règle utilisés ici correspondent à Android 5.1 et sont susceptibles d'être modifiés par la version.

Règle 48 : neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
Voir la page de manuel de ptrace . La capacité sys_ptrace accorde la possibilité de ptrace n'importe quel processus, ce qui permet un contrôle important sur les autres processus et ne doit appartenir qu'aux composants système désignés, décrits dans la règle. Le besoin de cette capacité indique souvent la présence de quelque chose qui n'est pas destiné aux versions destinées à l'utilisateur ou à une fonctionnalité qui n'est pas nécessaire. Retirez le composant inutile.

Règle 76 : neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
Cette règle est destinée à empêcher l'exécution de code arbitraire sur le système. Plus précisément, il affirme que seul le code sur /system est exécuté, ce qui permet des garanties de sécurité grâce à des mécanismes tels que le démarrage vérifié. Souvent, la meilleure solution lorsque vous rencontrez un problème avec cette règle neverallow est de déplacer le code incriminé vers la partition /system .

Personnalisation de SEPolicy dans Android 8.0+

Cette section fournit des directives pour la politique SELinux du fournisseur dans Android 8.0 et versions ultérieures, y compris des détails sur les extensions SEPolicy et SEPolicy d'Android Open Source Project (AOSP). Pour plus d'informations sur la manière dont la politique SELinux est maintenue compatible entre les partitions et les versions d'Android, consultez Compatibilité .

Emplacement de la politique

Dans Android 7.0 et versions antérieures, les fabricants d'appareils pouvaient ajouter une stratégie à BOARD_SEPOLICY_DIRS , y compris une stratégie destinée à augmenter la stratégie AOSP sur différents types d'appareils. Dans Android 8.0 et versions ultérieures, l'ajout d'une stratégie à BOARD_SEPOLICY_DIRS place la stratégie uniquement dans l'image du fournisseur.

Dans Android 8.0 et versions ultérieures, la politique existe dans les emplacements suivants dans AOSP :

  • système/sepolicy/public . Inclut la politique exportée pour être utilisée dans la politique spécifique au fournisseur. Tout rentre dans l' infrastructure de compatibilité Android 8.0. La politique publique est censée persister d'une version à l'autre afin que vous puissiez inclure tout ce qui est /public dans votre politique personnalisée. Pour cette raison, le type de stratégie pouvant être placé dans /public est plus restreint. Considérez ceci comme l'API de politique exportée de la plate-forme : tout ce qui concerne l'interface entre /system et /vendor appartient ici.
  • système/sepolicy/privé . Inclut la stratégie nécessaire au fonctionnement de l'image système, mais dont la stratégie d'image du fournisseur ne doit pas avoir connaissance.
  • système/sepolicy/fournisseur . Inclut la politique pour les composants qui vont dans /vendor mais qui existent dans l'arborescence de la plate-forme principale (pas les répertoires spécifiques à l'appareil). Il s'agit d'un artefact de la distinction du système de construction entre les appareils et les composants globaux ; conceptuellement, cela fait partie de la stratégie spécifique à l'appareil décrite ci-dessous.
  • appareil/ manufacturer / device-name /sepolicy . Inclut une politique spécifique à l'appareil. Inclut également les personnalisations de l'appareil à la stratégie, qui dans Android 8.0 et versions ultérieures correspondent à la stratégie des composants sur l'image du fournisseur.

Dans Android 11 et versions ultérieures, les partitions system_ext et produit peuvent également inclure des politiques spécifiques à la partition. system_ext et les politiques de produit sont également divisées en public et privé, et les fournisseurs peuvent utiliser les politiques publiques de system_ext et de produit, comme la politique système.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS . Inclut la politique exportée pour être utilisée dans la politique spécifique au fournisseur. Installé sur la partition system_ext.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS . Inclut la politique nécessaire au fonctionnement de l'image system_ext, mais dont la politique d'image du fournisseur ne doit pas avoir connaissance. Installé sur la partition system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS . Inclut la politique exportée pour être utilisée dans la politique spécifique au fournisseur. Installé sur la partition du produit.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS . Comprend la politique nécessaire au fonctionnement de l'image du produit, mais dont la politique d'image du fournisseur ne devrait pas avoir connaissance. Installé sur la partition du produit.
Remarque : lorsque GSI est utilisé, les partitions system_ext et produit OEM ne seront pas montées. Les règles de la stratégie de fournisseur qui utilisent la stratégie publique system_ext et produit de l'OEM deviennent NOP car les définitions de type spécifiques à l'OEM sont manquantes.
Remarque : Soyez très prudent lorsque vous utilisez system_ext et les politiques publiques du produit. Les politiques publiques agissent comme une API exportée entre system_ext/product et le fournisseur. Les partenaires sont censés gérer eux-mêmes les problèmes de compatibilité.

Scénarios de stratégie pris en charge

Sur les appareils lancés avec Android 8.0 et versions ultérieures, l'image du fournisseur doit fonctionner avec l'image système OEM et l'image système AOSP de référence fournies par Google (et transmettre le CTS sur cette image de référence). Ces exigences garantissent une séparation nette entre le framework et le code du fournisseur. Ces appareils prennent en charge les scénarios suivants.

extensions d'image de fournisseur uniquement

Exemple : Ajout d'un nouveau service à vndservicemanager à partir de l'image du fournisseur qui prend en charge les processus de l'image du fournisseur.

Comme pour les appareils lancés avec les versions précédentes d'Android, ajoutez une personnalisation spécifique à l'appareil dans device/ manufacturer / device-name /sepolicy . La nouvelle politique régissant la façon dont les composants du fournisseur interagissent avec (uniquement) d'autres composants du fournisseur devrait impliquer des types présents uniquement dans device/ manufacturer / device-name /sepolicy . La politique écrite ici permet au code du fournisseur de fonctionner, ne sera pas mise à jour dans le cadre d'un OTA uniquement cadre et sera présente dans la politique combinée sur un appareil avec l'image système AOSP de référence.

prise en charge de l'image du fournisseur pour travailler avec AOSP

Exemple : Ajout d'un nouveau processus (enregistré auprès de hwservicemanager à partir de l'image du fournisseur) qui implémente une HAL définie par AOSP.

Comme pour les appareils lancés avec les versions précédentes d'Android, effectuez une personnalisation spécifique à l'appareil dans device/ manufacturer / device-name /sepolicy . La politique exportée dans le cadre de system/sepolicy/public/ est disponible pour utilisation et est livrée avec la politique du fournisseur. Les types et attributs de la politique publique peuvent être utilisés dans de nouvelles règles dictant les interactions avec les nouveaux bits spécifiques au fournisseur, sous réserve des restrictions neverallow fournies. Comme dans le cas du fournisseur uniquement, la nouvelle stratégie ici ne sera pas mise à jour dans le cadre d'un OTA de cadre uniquement et sera présente dans la stratégie combinée sur un appareil avec l'image système AOSP de référence.

extensions d'image système uniquement

Exemple : Ajout d'un nouveau service (enregistré auprès de servicemanager) accessible uniquement par d'autres processus à partir de l'image système.

Ajoutez cette stratégie à system/sepolicy/private . Vous pouvez ajouter des processus ou des objets supplémentaires pour activer la fonctionnalité dans une image système partenaire, à condition que ces nouveaux bits n'aient pas besoin d'interagir avec de nouveaux composants sur l'image du fournisseur (en particulier, ces processus ou objets doivent fonctionner pleinement sans politique de l'image du fournisseur) . La stratégie exportée par system/sepolicy/public est disponible ici, tout comme pour les extensions d'image de fournisseur uniquement. Cette politique fait partie de l'image système et peut être mise à jour dans un cadre uniquement OTA, mais ne sera pas présente lors de l'utilisation de l'image système AOSP de référence.

extensions d'image de fournisseur qui servent des composants AOSP étendus

Exemple : Une nouvelle couche HAL non AOSP destinée à être utilisée par des clients étendus qui existent également dans l'image système AOSP (comme un serveur_système étendu).

La stratégie d'interaction entre le système et le fournisseur doit être incluse dans le répertoire device/ manufacturer / device-name /sepolicy fourni sur la partition du fournisseur. Ceci est similaire au scénario ci-dessus consistant à ajouter la prise en charge de l'image du fournisseur pour fonctionner avec l'image AOSP de référence, sauf que les composants AOSP modifiés peuvent également nécessiter une stratégie supplémentaire pour fonctionner correctement avec le reste de la partition système (ce qui est bien tant qu'ils sont toujours ont les labels publics de type AOSP).

La politique d'interaction des composants AOSP publics avec les extensions d'image système uniquement doit être dans system/sepolicy/private .

extensions d'image système qui accèdent uniquement aux interfaces AOSP

Exemple : Un nouveau processus système non AOSP doit accéder à une couche HAL sur laquelle AOSP s'appuie.

Ceci est similaire à l' exemple d'extension d'image système uniquement , sauf que de nouveaux composants système peuvent interagir à travers l'interface system/vendor . La politique pour le nouveau composant système doit aller dans system/sepolicy/private , ce qui est acceptable à condition que ce soit via une interface déjà établie par AOSP dans system/sepolicy/public (c'est-à-dire que les types et attributs requis pour la fonctionnalité sont là). Bien que la politique puisse être incluse dans la politique spécifique à l'appareil, elle ne pourrait pas utiliser d'autres types system/sepolicy/private ou changer (de quelque manière que ce soit affectant la politique) à la suite d'une mise à jour du cadre uniquement. La politique peut être modifiée dans un cadre OTA uniquement, mais ne sera pas présente lors de l'utilisation d'une image système AOSP (qui n'aura pas non plus le nouveau composant système).

extensions d'image de fournisseur qui servent de nouveaux composants système

Exemple : ajouter une nouvelle couche HAL non AOSP à utiliser par un processus client sans analogue AOSP (et nécessite donc son propre domaine).

Semblable à l' exemple d'extensions AOSP , la politique d'interactions entre le système et le fournisseur doit se trouver dans le répertoire device/ manufacturer / device-name /sepolicy livré sur la partition du fournisseur (pour s'assurer que la politique système n'a aucune connaissance des détails spécifiques au fournisseur). Vous pouvez ajouter de nouveaux types publics qui étendent la politique dans system/sepolicy/public ; cela ne devrait être fait qu'en plus de la politique AOSP existante, c'est-à-dire ne pas supprimer la politique publique AOSP. Les nouveaux types publics peuvent ensuite être utilisés pour la stratégie dans system/sepolicy/private et dans device/ manufacturer / device-name /sepolicy .

Gardez à l'esprit que chaque ajout à system/sepolicy/public ajoute de la complexité en exposant une nouvelle garantie de compatibilité qui doit être suivie dans un fichier de mappage et qui est soumise à d'autres restrictions. Seuls les nouveaux types et les règles d'autorisation correspondantes peuvent être ajoutés dans system/sepolicy/public ; les attributs et autres déclarations de stratégie ne sont pas pris en charge. De plus, les nouveaux types publics ne peuvent pas être utilisés pour étiqueter directement des objets dans la politique /vendor .

Scénarios de stratégie non pris en charge

Les appareils lancés avec Android 8.0 et versions ultérieures ne prennent pas en charge le scénario de stratégie et les exemples suivants.

Extensions supplémentaires à l'image système qui nécessitent une autorisation pour les nouveaux composants de l'image du fournisseur après un OTA de cadre uniquement

Exemple : un nouveau processus système non AOSP, nécessitant son propre domaine, est ajouté dans la prochaine version d'Android et doit accéder à un nouveau HAL non AOSP.

Similaire à l'interaction entre les nouveaux systèmes (non-AOSP) et les composants du fournisseur , sauf que le nouveau type de système est introduit dans un OTA uniquement structuré. Bien que le nouveau type puisse être ajouté à la politique dans system/sepolicy/public , la politique existante du fournisseur n'a aucune connaissance du nouveau type car elle ne suit que la politique publique du système Android 8.0. AOSP gère cela en exposant les ressources fournies par le fournisseur via un attribut (par exemple, l'attribut hal_foo ) mais comme les extensions de partenaire d'attribut ne sont pas prises en charge dans system/sepolicy/public , cette méthode n'est pas disponible pour la politique du fournisseur. L'accès doit être fourni par un type public existant précédemment.

Exemple : Une modification apportée à un processus système (AOSP ou non AOSP) doit modifier la manière dont il interagit avec le nouveau composant fournisseur non AOSP.

La stratégie sur l'image système doit être écrite sans connaissance des personnalisations spécifiques du fournisseur. La politique concernant des interfaces spécifiques dans AOSP est ainsi exposée via des attributs dans system/sepolicy/public afin que la politique du fournisseur puisse adhérer à la future politique système qui utilise ces attributs. Cependant, les extensions d'attributs dans system/sepolicy/public ne sont pas prises en charge , donc toutes les politiques dictant comment les composants du système interagissent avec les nouveaux composants du fournisseur (et qui ne sont pas gérées par les attributs déjà présents dans AOSP system/sepolicy/public ) doivent être dans device/ manufacturer / device-name /sepolicy . Cela signifie que les types de système ne peuvent pas modifier l'accès autorisé aux types de fournisseurs dans le cadre d'un OTA uniquement structuré.