Weryfikowanie SELinux

Android zdecydowanie zachęca producentów OEM do testowania implementacji SELinux. bardzo szybko. W miarę wdrażania SELinux producenci powinni stosować nowe do puli testowej urządzeń.

Po zastosowaniu nowej zasady sprawdź, czy SELinux działa w odpowiednim trybie na urządzeniu. Aby to zrobić, uruchom polecenie getenforce.

Powoduje to wydrukowanie globalnego trybu SELinux: wymuszania lub mniej rygorystycznego. Aby określić tryb SELinux dla każdej domeny, musisz sprawdzić odpowiednie pliki lub uruchomić najnowszą wersję sepolicy-analyze z odpowiednią flagą (-p), która znajduje się w /platform/system/sepolicy/tools/.

Odczytaj odmowy

Sprawdź, czy nie ma błędów, które są kierowane jako logi zdarzeń na adres dmesg i logcat. Są one widoczne lokalnie na urządzeniu. Producenci powinien sprawdzić wyjście SELinux na dmesg na tych urządzeniach i dopracować ustawienia przed opublikowaniem wersji w trybie mniej rygorystycznym w trybie wymuszania. Wiadomości z dziennika SELinux zawierają avc:, więc można je łatwo znaleźć za pomocą grep. Aby przechwycić bieżące logi odmowy, uruchom cat /proc/kmsg. Aby przechwycić logi odmowy z poprzedniego uruchomienia, uruchom cat /sys/fs/pstore/console-ramoops.

Częstotliwość komunikatów o błędach SELinux jest ograniczona po zakończeniu uruchamiania, aby zapobiec przewadze prądu. dzienniki. Aby mieć pewność, że widzisz wszystkie odpowiednie wiadomości, możesz wyłączyć tę funkcję, adb shell auditctl -r 0.

Na podstawie tych danych producenci mogą łatwo określić, czy użytkownicy systemu Naruszają zasadę SELinux. Producenci mogą naprawić to złe zachowanie, wprowadzając zmiany w oprogramowaniu lub zasadach SELinux albo w obu tych elementach.

W szczególności te komunikaty wskazują, które procesy nie będą działać w trybie egzekwowania i dlaczego. Oto przykład:

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

Zinterpretuj te dane wyjściowe w następujący sposób:

  • { connectto } powyżej wskazuje podjęte działanie. Wraz z tclass na końcu (unix_stream_socket) informuje, co zostało zrobione i dla kogo. W tym przypadku coś próbowało nawiązać połączenie z gniazdem strumieniowym Unixa.
  • scontext (u:r:shell:s0) informuje, w jakim kontekście zainicjowano działanie. W tym przypadku jest to coś, co działa jako powłoka.
  • tcontext (u:r:netd:s0) informuje o kontekście celu działania. W w tym przypadku jest to sieć unix_stream_socket należąca do netd.
  • Element comm="ping" na górze zawiera dodatkową wskazówkę dotyczącą uruchamianych w momencie wygenerowania odmowy. W tym przypadku jest to całkiem dobry wskazówek.

Inny przykład:

adb shell su root dmesg | grep 'avc: '

Urządzenie wyjściowe:

<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

Oto najważniejsze elementy tej odmowy:

  • Działanie – próba wykonania działania jest podświetlona w nawiasie. read write lub setenforce.
  • Uczestnik – wpis scontext (kontekst źródła) reprezentuje uczestnika, w tym przypadku demona rmt_storage.
  • Obiekt – wpis tcontext (kontekst docelowy) reprezentuje na obiekt, na którym wykonano działanie, w tym przypadku kmem.
  • Wynik – wpis tclass (klasa docelowa) wskazuje typ obiektu, na którym wykonywane jest działanie, w tym przypadku chr_file (urządzenie znakowe).

Wydumpowanie stosów użytkownika i jądra

W niektórych przypadkach informacje zawarte w dzienniku zdarzeń nie wystarczą do zidentyfikowania źródło zaprzeczania. Aby lepiej zrozumieć, dlaczego doszło do odrzucenia, często warto zebrać łańcuch wywołań, w tym dotyczące jądra i przestrzeni użytkownika.

Najnowsze jądra definiują punkt śledzenia o nazwie avc:selinux_audited. Użyj Androida simpleperf, aby włączyć ten punkt śledzenia i przechwycić łańcuch wywołań.

Obsługiwana konfiguracja

  • Jądro systemu Linux >= 5.10, zwłaszcza typowe gałęzie jądra systemu Android mainline oraz android12–5.10 są obsługiwane. Obsługiwana jest też gałąź android12-5.4. Możesz użyć parametru simpleperf, aby określić, czy punkt śledzenia to zdefiniowane na urządzeniu: adb root && adb shell simpleperf list | grep avc:selinux_audited W przypadku innych wersji jądra możesz wybrać zatwierdzenia. dd81662 oraz 30969bc.
  • Możliwe jest odtworzenie debugowanego zdarzenia. Zdarzenia w momencie uruchomienia nie są obsługiwane za pomocą Simpleperf; ale wciąż możesz spróbować ponownie ją uruchomić, aby aktywować usługę. do zdarzenia.

Rejestrowanie łańcucha wywołań

Najpierw należy zarejestrować zdarzenie za pomocą funkcji simpleperf record:

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

Następnie powinno zostać wywołane zdarzenie, które spowodowało odrzucenie. Następnie nagrywanie powinno zostać zatrzymane. W tym przykładzie próbka zostałaby zarejestrowana za pomocą funkcji Ctrl-c:

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

Na koniec możesz użyć parametru simpleperf report, aby sprawdzić zarejestrowany ślad stosu. Przykłady:

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

Powyższy łańcuch wywołań to ujednolicony jądro i łańcuch wywołań przestrzeni użytkownika. Zapewnia przepływu kodu przez uruchomienie śledzenia od przestrzeni użytkownika aż do jądra systemu następuje zaprzeczanie. Więcej informacji o simpleperf znajdziesz tutaj: Dokumentacja poleceń wykonywalnych Simpleperf

Przełącz na mniej rygorystyczny

Egzekwowanie SELinux można wyłączyć za pomocą narzędzia adb w kompilacji userdebug lub eng. Aby to zrobić: Najpierw przełącz ADB na konto roota, uruchamiając adb root. Aby wyłączyć SELinux, uruchom:

adb shell setenforce 0

W wierszu poleceń jądra (podczas wcześniejszego wywołania urządzenia):

androidboot.selinux=permissive
androidboot.selinux=enforcing

Możesz też użyć bootconfig w Androidzie 12:

androidboot.selinux=permissive
androidboot.selinux=enforcing

Używaj audyt2allow

Narzędzie audit2allow przekształca zaprzeczenia dmesg w odpowiednie oświadczenia o zasadach SELinux. Dzięki temu może znacznie przyspieszają programowanie SELinux.

Aby go użyć, uruchom:

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

Należy jednak zachować ostrożność podczas sprawdzania każdego potencjalnego dodania przekraczające uprawnienia. Na przykład w celu przesłania do aplikacji audit2allow Wcześniejsza odmowa z powodu rmt_storage skutkuje następującym wynikiem sugerowana instrukcja zasad SELinux:

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

Daje to usłudze rmt możliwość zapisu pamięci jądra, rzucił okiem na lukę w zabezpieczeniach. Często instrukcje audit2allow są tylko punktem wyjścia. Po zastosowaniu oświadczeń może być konieczna zmiana domeny źródłowej i etykiety celu oraz zastosuj odpowiednie w celu opracowania odpowiednich zasad. Czasami badana odmowa musi nie spowoduje żadnych zmian zasad; a nie aplikacji naruszającej zasady należy zmienić.