Android zdecydowanie zachęca producentów OEM do dokładnego testowania ich implementacji SELinux. Gdy producenci wdrażają SELinux, powinni najpierw zastosować nową politykę do testowej puli urządzeń.
Po zastosowaniu nowej polityki upewnij się, że SELinux działa we właściwym trybie na urządzeniu, wydając polecenie getenforce
.
Spowoduje to wydrukowanie globalnego trybu SELinux: Enforcing lub Permissive. Aby określić tryb SELinux dla każdej domeny, należy sprawdzić odpowiednie pliki lub uruchomić najnowszą wersję sepolicy-analyze
z odpowiednią flagą ( -p
), obecną w /platform/system/sepolicy/tools/
.
Zaprzeczenia czytania
Sprawdź błędy, które są kierowane jako dzienniki zdarzeń do dmesg
i logcat
i są widoczne lokalnie na urządzeniu. Producenci powinni sprawdzić dane wyjściowe SELinux do dmesg
na tych urządzeniach i udoskonalić ustawienia przed publicznym wydaniem w trybie zezwalającym i ewentualnym przejściem w tryb wymuszający. Komunikaty dziennika SELinux zawierają avc:
i dlatego można je łatwo znaleźć za pomocą grep
. Możliwe jest przechwycenie trwających dzienników odmów, uruchamiając cat /proc/kmsg
lub przechwycenie dzienników odmów z poprzedniego rozruchu, uruchamiając cat /sys/fs/pstore/console-ramoops
.
Komunikaty o błędach SELinux mają ograniczoną szybkość po zakończeniu rozruchu, aby uniknąć zapełnienia dzienników. Aby upewnić się, że widzisz wszystkie odpowiednie komunikaty, możesz to wyłączyć, uruchamiając adb shell auditctl -r 0
.
Dzięki tym wynikom producenci mogą łatwo zidentyfikować, kiedy użytkownicy lub komponenty systemu naruszają politykę SELinux. Producenci mogą następnie naprawić to złe zachowanie, zmieniając oprogramowanie, politykę SELinux lub jedno i drugie.
W szczególności te komunikaty dziennika wskazują, które procesy zakończą się niepowodzeniem w trybie wymuszania 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 to wyjście w następujący sposób:
-
{ connectto }
powyżej reprezentuje podejmowane działanie. Wraz ztclass
na końcu (unix_stream_socket
), mówi ci z grubsza, co było robione z czym. W tym przypadku coś próbowało połączyć się z gniazdem unix stream. -
scontext (u:r:shell:s0)
informuje, jaki kontekst zainicjował akcję. W tym przypadku jest to coś działającego jako powłoka. -
tcontext (u:r:netd:s0)
informuje o kontekście celu akcji. W tym przypadku jest to unix_stream_socket należący donetd
. -
comm="ping"
u góry daje dodatkową wskazówkę na temat tego, co było uruchamiane w momencie wygenerowania odmowy. W tym przypadku to całkiem dobra wskazówka.
Inny przykład:
adb shell su root dmesg | grep 'avc: '
Wyjście:
<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 kluczowe elementy tego zaprzeczenia:
- Akcja - próba akcji jest podświetlona w nawiasach,
read write
lubsetenforce
. - Aktor —
scontext
(kontekst źródłowy) reprezentuje aktora, w tym przypadku demonarmt_storage
. - Obiekt —
tcontext
(kontekst docelowy) reprezentuje obiekt, na którym wykonywane są działania, w tym przypadku kmem. - Wynik — wpis
tclass
(klasa docelowa) wskazuje typ obiektu, na którym wykonywane są działania, w tym przypadkuchr_file
(urządzenie znakowe).
Zrzucanie stosów użytkownika i jądra
W niektórych przypadkach informacje zawarte w dzienniku zdarzeń nie wystarczają do ustalenia źródła odmowy. Często przydatne jest zebranie łańcucha wywołań, w tym jądra i przestrzeni użytkownika, aby lepiej zrozumieć, dlaczego wystąpiła odmowa.
Najnowsze jądra definiują punkt śledzenia o nazwie avc:selinux_audited
. Użyj simpleperf
Androida, aby włączyć ten punkt śledzenia i przechwycić łańcuch wywołań.
Obsługiwana konfiguracja
- Jądro systemu Linux >= 5.10, w szczególności obsługiwane są główne gałęzie systemu Android Common Kernel i system Android 12-5.10 . Obsługiwana jest również gałąź Androida 12-5.4 . Możesz użyć
simpleperf
, aby określić, czy punkt śledzenia jest zdefiniowany na twoim urządzeniu:adb root && adb shell simpleperf list | grep avc:selinux_audited
. W przypadku innych wersji jądra możesz wybrać zatwierdzenia dd81662 i 30969bc . - Powinno być możliwe odtworzenie debugowanego zdarzenia. Zdarzenia czasu rozruchu nie są obsługiwane przy użyciu simpleperf; jednak nadal możesz być w stanie ponownie uruchomić usługę, aby wywołać zdarzenie.
Przechwytywanie łańcucha połączeń
Pierwszym krokiem jest zarejestrowanie zdarzenia za pomocą 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 odmowę. Po tym nagrywanie powinno zostać zatrzymane. W tym przykładzie przy użyciu Ctrl-c
próbka powinna zostać przechwycona:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Wreszcie, simpleperf report
może być użyty do sprawdzenia przechwyconego śladu stosu. Na przykład:
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 łańcuch wywołań jądra i przestrzeni użytkownika. Daje lepszy wgląd w przepływ kodu, rozpoczynając śledzenie od przestrzeni użytkownika aż do jądra, w którym następuje odmowa. Aby uzyskać więcej informacji na temat simpleperf
, zobacz informacje o poleceniach wykonywalnych Simpleperf
Przełączanie na permisywne
Wymuszanie SELinux można wyłączyć za pomocą ADB w kompilacjach userdebug lub eng. Aby to zrobić, najpierw przełącz ADB na root, uruchamiając adb root
. Następnie, aby wyłączyć wymuszanie SELinux, uruchom:
adb shell setenforce 0
Lub w wierszu poleceń jądra (podczas wczesnego uruchamiania urządzenia):
androidboot.selinux=permissive
androidboot.selinux=enforcing
Lub przez bootconfig w Androidzie 12:
androidboot.selinux=permissive
androidboot.selinux=enforcing
Korzystanie z audit2allow
Narzędzie audit2allow
pobiera odmowy dmesg
i konwertuje je na odpowiednie deklaracje polityki SELinux. W związku z tym może znacznie przyspieszyć rozwój SELinuksa.
Aby go użyć, uruchom:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
Niemniej jednak należy zachować ostrożność, aby zbadać każdy potencjalny dodatek pod kątem przekroczenia uprawnień. Na przykład podawanie audit2allow
odmowy rmt_storage
pokazanej wcześniej skutkuje następującym sugerowanym oświadczeniem polityki SELinux:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
Dałoby to rmt
możliwość zapisywania pamięci jądra, co jest rażącą luką w zabezpieczeniach. Często instrukcje audit2allow
są tylko punktem wyjścia. Po zastosowaniu tych instrukcji może być konieczna zmiana domeny źródłowej i etykiety celu, a także włączenie odpowiednich makr, aby uzyskać dobrą politykę. Czasami badana odmowa nie powinna w ogóle powodować żadnych zmian w polityce; raczej należy zmienić aplikację naruszającą prawo.