SELinux prüfen

Android empfiehlt OEMs dringend, ihre SELinux-Implementierungen gründlich zu testen. Wenn Hersteller SELinux implementieren, sollten sie die neue Richtlinie zuerst auf einen Testpool von Geräten anwenden.

Nachdem Sie eine neue Richtlinie angewendet haben, stellen Sie sicher, dass SELinux im richtigen auf dem Gerät mit dem Befehl getenforce.

Damit wird der globale SELinux-Modus ausgegeben: entweder „Erzwingen“ oder „Moderat“. Bis den SELinux-Modus für jede Domain ermitteln, müssen Sie die entsprechenden -Dateien oder die neueste Version von sepolicy-analyze mit dem entsprechende Markierung (-p), vorhanden in /platform/system/sepolicy/tools/.

Ablehnungen lesen

Prüfen Sie auf Fehler, die als Ereignisprotokolle an dmesg und logcat weitergeleitet und lokal auf dem Gerät angezeigt werden. Hersteller sollten die SELinux-Ausgabe an dmesg auf diesen Geräten prüfen und die Einstellungen vor der Veröffentlichung im permissiven Modus optimieren und gegebenenfalls in den Erzwingungsmodus wechseln. SELinux-Logmeldungen enthalten avc: und somit mit grep leicht gefunden werden. Sie können die laufenden Deaktivierungsprotokolle mit cat /proc/kmsg erfassen oder die Deaktivierungsprotokolle vom vorherigen Start mit cat /sys/fs/pstore/console-ramoops.

SELinux-Fehlermeldungen werden nach dem Starten mit einer Ratenbegrenzung versehen, um eine Überlastung der Protokolle zu vermeiden. Wenn Sie alle relevanten Nachrichten sehen möchten, können Sie diese Funktion deaktivieren, indem Sie adb shell auditctl -r 0 eingeben.

Anhand dieser Ausgabe können Hersteller sofort erkennen, Komponenten verstoßen gegen die SELinux-Richtlinie. Hersteller können dieses Fehlverhalten dann beheben, entweder durch Änderungen an der Software, an der SELinux-Richtlinie oder an beiden.

Insbesondere geben diese Logmeldungen an, welche Prozesse im Erzwingungsmodus fehlschlagen würden und warum. Hier ein Beispiel:

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

Interpretieren Sie diese Ausgabe so:

  • Das { connectto } oben steht für die ausgeführte Aktion. Zusammen mit dem tclass am Ende (unix_stream_socket) erfahren Sie ungefähr, was mit was gemacht wurde. In diesem Fall wurde versucht, eine Verbindung zu einem Unix-Stream-Socket herzustellen.
  • Die scontext (u:r:shell:s0) gibt Aufschluss darüber, in welchem Kontext die Aktion ausgelöst wurde. In In diesem Fall wird das als Shell ausgeführt.
  • tcontext (u:r:netd:s0) gibt den Kontext des Ziels der Aktion an. In In diesem Fall ist das ein Unix_stream_Socket von netd.
  • Das comm="ping" ganz oben gibt Ihnen einen zusätzlichen Hinweis darauf, was gerade angezeigt wurde. ausgeführt wurde, als die Ablehnung generiert wurde. In diesem Fall ist es ein ziemlich guter Hinweis.

Ein weiteres Beispiel:

adb shell su root dmesg | grep 'avc: '

Ausgabe:

<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

Hier sind die wichtigsten Elemente dieser Ablehnung:

  • Aktion: Die versuchte Aktion ist in Klammern hervorgehoben: read write oder setenforce.
  • Akteur: Der Eintrag scontext (Quellkontext) steht für den Akteur, in diesem Fall den Daemon rmt_storage.
  • Objekt: Der Eintrag tcontext (Zielkontext) steht für das Objekt, auf das eine Aktion angewendet wird, in diesem Fall kmem.
  • Ergebnis: Der Eintrag tclass (Zielklasse) gibt den Typ an. des Objekts, auf das reagiert wird, in diesem Fall chr_file (Zeichengerät).

Dump-Nutzer- und Kernel-Stacks

In einigen Fällen reichen die Informationen im Ereignisprotokoll nicht aus, um die Ursache der Ablehnung zu ermitteln. Es ist oft hilfreich, die Aufrufabfolge zu erfassen, einschließlich Kernel und Userspace, um besser nachvollziehen zu können, warum die Zugriffsverweigerung aufgetreten ist.

Neuere Kernel definieren einen Tracepoint mit dem Namen avc:selinux_audited. Verwenden Sie Android simpleperf, um diesen Tracepoint zu aktivieren und die Aufrufabfolge aufzuzeichnen.

Unterstützte Konfiguration

  • Linux-Kernel >= 5.10, insbesondere Android Common Kernel-Zweige Mainline und android12–5.10 unterstützt werden. Der Branch android12-5.4 wird ebenfalls unterstützt. Mit simpleperf können Sie prüfen, ob der Tracepoint auf Ihrem Gerät definiert ist: adb root && adb shell simpleperf list | grep avc:selinux_audited. Bei anderen Kernelversionen können Sie die Commits dd81662 und 30969bc auswählen.
  • Das Ereignis, das Sie beheben möchten, sollte reproduzierbar sein. Ereignisse zur Bootzeit werden von simpleperf nicht unterstützt. Sie können den Dienst jedoch neu starten, um das Ereignis auszulösen.

Aufrufkette erfassen

Der erste Schritt besteht darin, das Ereignis mit simpleperf record aufzuzeichnen:

adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"

Dann sollte das Ereignis ausgelöst werden, das die Ablehnung verursacht hat. Danach sollte die Aufzeichnung dass sie gestoppt werden. In diesem Beispiel sollte die Stichprobe durch die Verwendung von Ctrl-c erfasst worden sein:

^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.

Mit simpleperf report können Sie den erfassten Stacktrace prüfen. Beispiel:

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

Die obige Aufrufabfolge ist eine einheitliche Aufrufabfolge für Kernel und Userspace. Sie erhalten eine bessere des Codeflusses ansehen, indem wir das Trace vom Userspace bis zum Kernel starten, die Leugnung passiert. Weitere Informationen zu simpleperf finden Sie in der Referenz zu ausführbaren Simpleperf-Befehlen.

Zu moderat wechseln

Die SELinux-Erzwigung kann mit adb bei Userdebug- oder eng-Builds deaktiviert werden. Gehen Sie dazu wie folgt vor: Wechsle zuerst ADB zum Root, indem du adb root ausführst. Führen Sie dann diesen Befehl aus, um die SELinux-Erzwigung zu deaktivieren:

adb shell setenforce 0

Oder in der Kernel-Befehlszeile (während der frühen Geräteeinrichtung):

androidboot.selinux=permissive
androidboot.selinux=enforcing

Oder über „bootconfig“ in Android 12:

androidboot.selinux=permissive
androidboot.selinux=enforcing

Audit2allow verwenden

Das audit2allow-Tool wandelt dmesg-Abweisungen in entsprechende SELinux-Richtlinienausdrücke um. So kann die SELinux-Entwicklung erheblich beschleunigt werden.

Führen Sie folgenden Befehl aus, um sie zu verwenden:

adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy

Dennoch muss jede mögliche Ergänzung für zu viele Berechtigungen. Wenn Sie z. B. audit2allow mit dem Die vorherige Ablehnung von rmt_storage führt zu folgendem Ergebnis: vorgeschlagene SELinux-Richtlinienanweisung:

#============= shell ==============
allow shell kernel:security setenforce;
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };

Dadurch hätte rmt die Möglichkeit, Kernel-Speicher zu schreiben, was ein eklatantes Sicherheitsrisiko darstellt. Häufig sind die audit2allow-Anweisungen nur eine Ausgangspunkt ist. Nachdem Sie diese Anweisungen verwendet haben, müssen Sie möglicherweise die Quelldomain und das Label des Ziels ändern und die richtigen Makros einbinden, um eine gute Richtlinie zu erhalten. Manchmal sollte die zu prüfende Ablehnung keinerlei Richtlinienänderungen zur Folge haben. und nicht auf die problematische App, geändert werden sollte.