1 votes

Comment ajouter une politique SELinux sur une ROM de débogage utilisateur qui a un schéma de politique `split`?

J'ai un appareil Sony qui prend en charge treble et qui est un appareil system-as-root et A/B. Il a une ROM user-debug installée dessus, donc son shell adb est rooté.

J'ai désactivé dm-verity en utilisant adb disable-verity après avoir exécuté les commandes adb root et adb remount.

Comme documenté ici, cet appareil a également des politiques split à /system/etc/selinux (la partie 'plat' de la politique) et /vendor/etc/selinux (la partie 'nonplat' de la politique).

J'essaie d'exécuter test.sh en utilisant le script d'initialisation suivant :

#/etc/init/m_daemon.rc

# définir le service, utiliser l'exécutable ici si le script n'est pas nécessaire
service m_daemon /system/xbin/test.sh

# ne démarre pas à moins d'être explicitement demandé
disabled

# Utilisez `seclabel u:r:magisk:s0` pour exécuter avec un contexte SELinux non restreint pour éviter les refus avc
# peut également utiliser "u:r:su:s0" sur les compiles userdebug / eng s'il n'y a pas de Magisk.
# C'est nécessaire si SELinux est en vigueur et que le service a besoin d'accéder
# à certaines ressources système non autorisées par défaut dans sepolicy
# seclabel u:object_r:qlogd_exec:s0
seclabel u:r:su:s0

# démarrer le service lorsque le démarrage est terminé
on property:sys.boot_completed=1
# Utilisez-le pour démarrer le service
start m_daemon

Le fichier /system/xbin/test.sh a le contenu suivant :

#!/system/bin/sh
echo `date` > /sdcard/test

Lorsque l'appareil redémarre, il échoue à s'exécuter avec l'erreur suivante :

202.932913 / 11-26 20:21:04.074 audit : type=1400 audit(1574763664.074:213) : avc : refusé { transition } pour pid=8534 comm="init" path="/system/xbin/test.sh" dev="sda24" ino=8150 scontext=u:r:init:s0 tcontext=u:r:su:s0 tclass=process permissif=0

202.933268 / 11-26 20:21:04.074 init: impossible d'exécuter('/system/xbin/test.sh') : Permission refusée

Pour résoudre ce problème, j'ai utilisé sepolicy-inject et exécuté les commandes suivantes :

sepolicy-inject -s init -t su -c process -p transition -P /sys/fs/selinux/policy -l
sepolicy-inject -s init -t su -c process -p noatsecure -P /sys/fs/selinux/policy -l
sepolicy-inject -s init -t su -c process -p rlimitinh -P /sys/fs/selinux/policy -l
sepolicy-inject -s init -t su -c process -p siginh -P /sys/fs/selinux/policy -l

mais cela doit être exécuté à nouveau après le redémarrage.

Donc, j'ai essayé de patcher precompiled_sepolicy en utilisant les commandes suivantes :

sepolicy-inject -s init -t su -c process -p transition -P /vendor/etc/selinux/precompiled_sepolicy -l
sepolicy-inject -s init -t su -c process -p noatsecure -P /vendor/etc/selinux/precompiled_sepolicy -l
sepolicy-inject -s init -t su -c process -p rlimitinh -P /vendor/etc/selinux/precompiled_sepolicy -l
sepolicy-inject -s init -t su -c process -p siginh -P /vendor/etc/selinux/precompiled_sepolicy -l

mais les politiques ne sont pas injectées : ni en direct, ni après le redémarrage.

Pour tester, je vérifie juste la date dans le fichier /sdcard/test.

Alors, je veux juste savoir :

  • Pourquoi le patching de precompiled_sepolicy n'a pas fonctionné ?
  • Où injecter les politiques requises en utilisant un shell adb rooté qui devraient persister après un redémarrage ?

1voto

Vatish Sharma Points 761

Pour corriger les politiques, faites ce qui suit :

  1. Changez la valeur dans /system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256 OU videz ce fichier.
  2. Injectez les politiques requises dans /system/etc/selinux/plat_sepolicy.cil
  3. "Chargement de la politique SELinux compilée" devrait s'afficher dans les journaux et le service init fonctionnera correctement.

0voto

Alhyoss Points 31

Comme je crois que la réponse répond à vos questions, voici une copie/collage sans honte de ma réponse à cette question :

Notez que cette réponse se concentrera uniquement sur Android 9 à 13 et sur les appareils Treble.

Si nous voulons savoir comment modifier les politiques SELinux, je crois qu'il est bon de comprendre d'abord comment ces politiques sont chargées en premier lieu.

SELinux dans le processus de démarrage

À un stade précoce du processus de démarrage Android et après le montage de la plupart des partitions, init tentera de charger les politiques SELinux à partir d'un fichier sepolicy monolithique trouvé soit à /odm/etc/selinux/precompiled_sepolicy soit à /vendor/etc/selinux/precompiled_sepolicy. Si init remarque que l'appareil est mis à jour hors synchronisation, init recompilera alors les politiques SELinux basées sur des fichiers .cil qui peuvent être trouvés à plusieurs endroits.

Vous pouvez trouver tous les détails dans les commentaires du fichier source init/selinux.cpp et en examinant l'implémentation, mais voici un résumé des étapes exactes prises par init :

  1. Trouver le fichier sepolicy à utiliser :
    • si /odm/etc/selinux/precompiled_sepolicy existe, l'utiliser comme fichier sepolicy à utiliser
    • sinn, si /vendor/etc/selinux/precompiled_sepolicy existe, l'utiliser comme fichier sepolicy à utiliser
    • sinn si aucun des deux n'existe, arrêter ici, recompiler les politiques basées sur les fichiers .cil et charger le fichier sepolicy nouvellement compilé.
  2. Vérifier si l'appareil a été mis à jour hors synchronisation :
    • Comparer /(odm|vendor)/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 et /system/etc/selinux/plat_sepolicy_and_mapping.sha256
    • Comparer /(odm|vendor)/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 et /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256
    • Comparer /(odm|vendor)/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 et /product/etc/selinux/product_sepolicy_and_mapping.sha256
    • (Sur Android 13) Comparer /(odm|vendor)/etc/selinux/precompiled_sepolicy.apex_sepolicy.sha256 et /dev/selinux/apex_sepolicy.sha256
    • si l'un des fichiers ci-dessus ne correspondent pas, arrêter ici, recompiler les politiques basées sur les fichiers .cil et charger le fichier sepolicy nouvellement compilé.
  3. Si tout est correct, charger le fichier sepolicy précompilé (/odm/etc/selinux/precompiled_sepolicy ou /vendor/etc/selinux/precompiled_sepolicy)

La compilation des politiques basées sur les fichiers .cil se déroule comme suit :

  1. Obtenir la dernière version des politiques compatibles avec la version vendor (/vendor/etc/selinux/plat_sepolicy_vers.txt, notez que init ne regarde pas le fichier dans la partition /odm)
  2. Rassembler les fichiers .cil à compiler :
    • /system/etc/selinux/mapping/{vendor_version}.cil
    • /system/etc/selinux/mapping/{vendor_version}.compat.cil
    • /system_ext/etc/selinux/system_ext_sepolicy.cil
    • /system_ext/etc/selinux/mapping/{vendor_version}.cil
    • /product/etc/selinux/product_sepolicy.cil
    • /product/etc/selinux/mapping/{vendor_version}.cil
    • /vendor/etc/selinux/plat_pub_versioned.cil
    • /vendor/etc/selinux/vendor_sepolicy.cil ou s'il n'existe pas : /vendor/etc/selinux/nonplat_sepolicy.cil
    • /odm/etc/selinux/odm_sepolicy.cil
  3. Compiler les fichiers ci-dessus avec secilc vers /dev/sepolicy.XXXXXX
  4. Charger les politiques depuis /dev/sepolicy.XXXXXX

Modification des politiques SELinux de manière permanente

Maintenant que nous comprenons comment init charge les politiques, il est facile de voir comment on pourrait ajouter de manière permanente de nouvelles politiques au système :

  • Ajouter directement les politiques à /odm/etc/selinux/precompiled_sepolicy ou /vendor/etc/selinux/precompiled_sepolicy avec sepolicy-inject :

    sepolicy-inject -s su -t system_file -c file -p entrypoint -P /vendor/etc/selinux/precompiled_sepolicy -o /vendor/etc/selinux/precompiled_sepolicy
  • Faire en sorte que init pense que l'appareil est mis à jour hors synchronisation (en modifiant l'un des fichiers .sha256 ci-dessus, ou en supprimant les fichiers de politiques sepolicy précompilées) et modifier l'un des fichiers .cil ci-dessus

Notez que dans les deux cas, vous devrez avoir un accès en écriture à la partition que vous souhaitez modifier (/vendor, /odm, et/ou /system). Ces partitions sont normalement montées en lecture seule, vous devrez donc soit :

  • Les remonter en écriture si vous avez un accès root (soit parce que votre appareil est rooté, soit en utilisant adb root sur une version Android userdebug)
  • Démarrer en mode de récupération, monter les partitions en écriture et les modifier en récupération

Si vous ne voulez pas devoir remonter les partitions à chaque fois que vous voulez modifier les politiques SELinux, vous pouvez ajouter quelques règles SELinux pour permettre à init de charger de nouvelles politiques, résolvant ainsi le problème du serpent qui se mord la queue (comme mentionné dans cette excellente réponse) que vous aviez avec votre script init. Vous pouvez trouver quelles règles SELinux sont nécessaires en recherchant des violations SELinux (erreurs avc) dans les journaux de l'appareil au démarrage :

adb logcat | grep avc

Avec cela, vous pourrez avoir un script init qui charge de nouvelles politiques avec sepolicy-inject.

androidalle.com

AndroidAlle est une communauté de androiders où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X