Android encourage vivement les OEM à tester leurs implémentations SELinux minutieusement. Les fabricants qui implémentent SELinux doivent appliquer le nouveau à un pool d'appareils de test.
Après avoir appliqué une nouvelle règle, assurez-vous que SELinux s'exécute dans le bon
sur l'appareil en émettant la commande getenforce
.
Le mode global SELinux s'affiche: Enforcing ou Permissive. À
déterminer le mode SELinux pour chaque domaine, vous devez examiner les
ou exécutez la dernière version de sepolicy-analyze
avec la
l'indicateur approprié (-p
), présent dans
<ph type="x-smartling-placeholder"></ph>
/platform/system/sepolicy/tools/
Lecture des refus
Rechercher les erreurs, qui sont acheminées en tant que journaux d'événements vers dmesg
et logcat
, et sont visibles localement sur l'appareil. Fabricants
doit examiner la sortie SELinux vers dmesg
sur ces périphériques et
Affiner les paramètres avant la publication en mode permissif et en cas de changement
au mode d'application. Les messages de journal SELinux contiennent avc:
. Il se peut donc
facilement avec grep
. Il est possible de capturer l'état actuel
les journaux de refus en exécutant cat /proc/kmsg
ou pour capturer les journaux de refus
du démarrage précédent en exécutant
cat /sys/fs/pstore/console-ramoops
Le taux de messages d'erreur SELinux est limité une fois le démarrage terminé afin d'éviter la surcharge
les journaux. Pour être sûr de voir tous les messages pertinents, vous pouvez désactiver cette
en exécutant adb shell auditctl -r 0
.
Avec ce résultat, les fabricants peuvent facilement identifier quand les utilisateurs ou ne respectent pas le règlement SELinux. Les fabricants peuvent alors réparer ce comportement insatisfaisant, soit par des modifications du logiciel, la politique SELinux, ou les deux.
Plus précisément, ces messages de journal indiquent quels processus échoueraient sous mode d'application et pourquoi. Voici un exemple :
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
Interprétez ce résultat comme suit:
- Le
{ connectto }
ci-dessus représente l'action en cours. En collaboration avectclass
à la fin (unix_stream_socket
), il vous indique à peu près ce qui a été fait à quoi. Dans ce cas, quelque chose tentait de se connecter à un socket de flux Unix. -
scontext (u:r:shell:s0)
vous indique le contexte à l'origine de l'action. Dans dans ce cas, c'est quelque chose qui s'exécute en tant que shell. -
tcontext (u:r:netd:s0)
vous indique le contexte de la cible de l'action. Dans dans ce cas, il s'agit d'un unix_stream_socket appartenant ànetd
. - Le
comm="ping"
en haut de la page fournit des indications supplémentaires sur le problème rencontré. exécutée au moment où le refus a été généré. Dans ce cas, c'est une très bonne astuce.
Autre exemple:
adb shell su root dmesg | grep 'avc: '
Sortie :
<5> type=1400 audit: avc: denied { read write } for pid=177 comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 tcontext=u:object_r:kmem_device:s0 tclass=chr_file
Voici les principaux éléments de ce refus:
- Action : l'action tentée est mise en évidence entre crochets.
read write
ousetenforce
. - Acteur : l'entrée
scontext
(contexte source) représente l'acteur, ici le daemonrmt_storage
. - Objet : l'entrée
tcontext
(contexte cible) représente l'objet concerné, dans ce cas kmem. - Résultat : l'entrée
tclass
(target class) indique le type. de l'objet concerné, dans ce cas unchr_file
(dispositif de caractère).
Vidage des piles utilisateur et du noyau
Dans certains cas, les informations contenues dans le journal des événements ne suffisent pas à identifier l'origine du refus. Il est souvent utile de rassembler la chaîne d'appel, y compris le noyau et l’espace utilisateur, afin de mieux comprendre pourquoi le refus s’est produit.
Les noyaux récents définissent un point de trace nommé avc:selinux_audited
. Utiliser Android
simpleperf
pour activer ce point de trace et capturer la chaîne d'appel.
Configuration compatible
- Noyau Linux 5.10 ou version ultérieure, en particulier les branches du kernel commun Android
ligne principale
et
android12-5.10
sont pris en charge.
android12-5.4
est également prise en charge. Vous pouvez utiliser
simpleperf
pour déterminer si le point de trace est défini sur votre appareil:adb root && adb shell simpleperf list | grep avc:selinux_audited
Pour les autres versions de noyau, vous pouvez choisir des commits dd81662. et 30969bc - L'événement que vous déboguez doit pouvoir être reproduit. Les événements de temps de démarrage compatibles avec simpleperf ; mais vous pourrez peut-être redémarrer le service pour déclencher l'événement.
Capturer la chaîne d'appel
La première étape consiste à enregistrer l'événement à l'aide de simpleperf record
:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
L'événement à l'origine du refus doit alors être déclenché. Après cela, l'enregistrement doit
être arrêté. Dans cet exemple, l'échantillon aurait dû être capturé à l'aide de Ctrl-c
:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Enfin, simpleperf report
peut être utilisé pour inspecter la trace de la pile capturée.
Exemple :
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph" [...] Children Self Command Pid Tid Shared Object Symbol 100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init | -- __libc_init | -- main toybox_main toy_exec_which dmesg_main klogctl entry_SYSCALL_64_after_hwframe do_syscall_64 __x64_sys_syslog do_syslog selinux_syslog slow_avc_audit common_lsm_audit avc_audit_post_callback avc_audit_post_callback
La chaîne d'appel ci-dessus est une chaîne d'appel unifiée
du noyau et de l'espace utilisateur. Il vous offre une meilleure
du flux de code en démarrant la trace de l'espace utilisateur jusqu'au noyau, où
le refus se produit. Pour en savoir plus sur simpleperf
, consultez les
Documentation de référence sur les commandes exécutables Simpleperf
Passer à un modèle permissif
L'application forcée de SELinux peut être désactivée via ADB sur userdebug ou eng builds. Pour ce faire,
Commencez par faire passer ADB en mode root en exécutant adb root
. Ensuite, pour
désactiver SELinux,
exécutez la commande suivante:
adb shell setenforce 0
Ou sur la ligne de commande du noyau (lors de l'utilisation initiale de l'appareil):
androidboot.selinux=permissive
androidboot.selinux=enforcing
Ou via bootconfig sous Android 12:
androidboot.selinux=permissive
androidboot.selinux=enforcing
Utiliser audit2allow
<ph type="x-smartling-placeholder">L'outil audit2allow
prend les refus dmesg
et
les convertit en déclarations de
politique SELinux correspondantes. À ce titre, elle peut
accélère considérablement le développement de SELinux.
Pour l'utiliser, exécutez la commande suivante:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
Néanmoins, il convient d'examiner attentivement chaque ajout potentiel pour
les autorisations excessives. Par exemple, en alimentant audit2allow
le
Le refus de rmt_storage
affiché précédemment entraîne les conséquences suivantes :
Suggestion de déclaration de règle SELinux:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
Cela donnerait à rmt
la possibilité d'écrire dans la mémoire du noyau, une
une faille de sécurité flagrante. Souvent, les instructions audit2allow
ne sont
point de départ. Après avoir utilisé ces instructions, vous devrez peut-être modifier la
le domaine source et le libellé de la cible, et intégrez les
pour obtenir une stratégie efficace. Parfois, le déni examiné
n'entraîner aucune modification des règles ; L'application incriminée
doit être modifiée.