SELinux jest domyślnie skonfigurowany tak, aby odmawiać dostępu. Oznacza to, że każdy dostęp, do którego ma on zaczep w jądrze, musi być wyraźnie dozwolony przez zasady. Plik zasad zawiera więc dużą ilość informacji o regułach, typach, klasach, uprawnieniach i innych elementach. Szczegółowe omówienie SELinux wykracza poza zakres tego dokumentu, ale zrozumienie, jak pisać reguły zasad, jest teraz niezbędne podczas konfigurowania nowych urządzeń z Androidem. Dostępnych jest już wiele informacji o SELinux. Sugerowane materiały znajdziesz w Supporting documentation dokumentacji pomocniczej.
Kluczowe pliki
Aby włączyć SELinux, zintegruj najnowsze jądro Androida, a następnie włącz pliki znajdujące się w katalogu system/sepolicy. Po skompilowaniu pliki te tworzą zasady bezpieczeństwa jądra SELinux i obejmują system operacyjny Android.
Zasadniczo nie należy bezpośrednio modyfikować plików system/sepolicy. Zamiast tego dodaj lub edytuj własne pliki zasad specyficzne dla urządzenia w
/device/manufacturer/device-name/sepolicy
katalogu. W Androidzie 8.0 i nowszych wersjach zmiany wprowadzane w tych plikach powinny wpływać tylko na zasady w katalogu dostawcy. Więcej informacji o rozdzieleniu
publicznych zasad SELinux w Androidzie 8.0 i nowszych wersjach znajdziesz w artykule
Dostosowywanie zasad SELinux w Androidzie
8.0 i nowszych wersjach. Niezależnie od wersji Androida nadal modyfikujesz te pliki:
Pliki zasad
Pliki kończące się na *.te to pliki źródłowe zasad SELinux, które definiują domeny i ich etykiety. Może być konieczne utworzenie nowych plików zasad w
/device/manufacturer/device-name/sepolicy,
ale w miarę możliwości należy aktualizować istniejące pliki.
Pliki kontekstu
W plikach kontekstu określasz etykiety obiektów.
file_contextsprzypisuje etykiety do plików i jest używany przez różne komponenty przestrzeni użytkownika. Podczas tworzenia nowych zasad utwórz lub zaktualizuj ten plik aby przypisać nowe etykiety do plików. Aby zastosować nowefile_contexts, ponownie skompiluj obraz systemu plików lub uruchomrestoreconw pliku, który ma zostać ponownie oznaczony. Podczas aktualizacji zmiany wfile_contextssą automatycznie stosowane do partycji systemowej i partycji danych użytkownika w ramach aktualizacji. Zmiany można też automatycznie zastosować podczas aktualizacji do innych partycji, dodającrestorecon_recursivewywołania do pliku init.board.rc po zamontowaniu partycji w trybie odczytu i zapisu.genfs_contextsprzypisuje etykiety do systemów plików, takich jakprocczyvfat, które nie obsługują rozszerzonych atrybutów. Ta konfiguracja jest wczytywana jako część zasad jądra, ale zmiany mogą nie zostać zastosowane do inode w jądrze, co wymaga ponownego uruchomienia lub odmontowania i ponownego zamontowania systemu plików. Określone etykiety można też przypisać do określonych punktów montowania, np.vfatza pomocą opcjicontext=mount.property_contextsprzypisuje etykiety do właściwości systemu Android, aby kontrolować, które procesy mogą je ustawiać. Ta konfiguracja jest odczytywana przezinitproces podczas uruchamiania.service_contextsprzypisuje etykiety do usług Android Binder, aby kontrolować, które procesy mogą dodawać (rejestrować) i znajdować (wyszukiwać) odniesienie do usługi. Ta konfiguracja jest odczytywana przezservicemanagerproces podczas uruchamiania.seapp_contextsprzypisuje etykiety do procesów aplikacji i/data/datakatalogów. Ta konfiguracja jest odczytywana przez proceszygoteprzy każdym uruchomieniu aplikacji oraz przezinstalldpodczas uruchamiania.mac_permissions.xmlprzypisuje tagseinfodo aplikacji na podstawie ich podpisu i opcjonalnie nazwy pakietu. Tagseinfomożna następnie użyć jako klucza w plikuseapp_contexts, aby przypisać określoną etykietę do wszystkich aplikacji z tym tagiemseinfo. Ta konfiguracja jest odczytywana przezsystem_serverpodczas uruchamiania.keystore2_key_contextsprzypisuje etykiety do przestrzeni nazw Keystore 2. Te przestrzenie nazw są wymuszane przez demonakeystore2. Keystore zawsze udostępniał przestrzenie nazw oparte na UID/AID. Keystore 2 dodatkowo wymusza przestrzenie nazw zdefiniowane przez zasady SELinux. Szczegółowy opis formatu i konwencji tego pliku znajdziesz tutaj.
Plik makefile BoardConfig.mk
Po edytowaniu lub dodaniu plików zasad i kontekstu zaktualizuj swój
/device/manufacturer/device-name/BoardConfig.mk
plik makefile, aby odwoływał się do podkatalogu sepolicy i każdego nowego pliku zasad.
Więcej informacji o zmiennych BOARD_SEPOLICY znajdziesz w pliku
system/sepolicy/README.
BOARD_SEPOLICY_DIRS += \
<root>/device/manufacturer/device-name/sepolicy
BOARD_SEPOLICY_UNION += \
genfs_contexts \
file_contexts \
sepolicy.te
Po ponownym skompilowaniu na urządzeniu jest włączony SELinux. Możesz teraz dostosować zasady SELinux, aby uwzględnić własne dodatki do systemu operacyjnego Android, zgodnie z opisem w sekcji Dostosowywanie, lub sprawdzić istniejącą konfigurację zgodnie z opisem w sekcji Weryfikacja.
Gdy nowe pliki zasad i aktualizacje BoardConfig.mk są na miejscu, nowe ustawienia zasad są automatycznie wbudowywane w końcowy plik zasad jądra. Więcej informacji o tym, jak tworzone są zasady SELinux na urządzeniu, znajdziesz w artykule Tworzenie zasad SELinux.
Implementacja
Aby rozpocząć korzystanie z SELinux:
- Włącz SELinux w jądrze:
CONFIG_SECURITY_SELINUX=y - Zmień parametr kernel_cmdline lub bootconfig tak, aby:
lubBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Jest to potrzebne tylko do wstępnego opracowania zasad dla urządzenia. Gdy masz już wstępne zasady bootstrap, usuń ten parametr, aby urządzenie wymuszało zasady lub nie przeszło testów CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Uruchom system w trybie zezwalającym i sprawdź, jakie odmowy występują podczas uruchamiania:
W Ubuntu 14.04 lub nowszym: W Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Sprawdź, czy w danych wyjściowych nie ma ostrzeżeń podobnych do
init: Warning! Service name needs a SELinux domain defined; please fix!. Instrukcje i narzędzia znajdziesz w sekcji Weryfikacja. - Określ urządzenia i inne nowe pliki, które wymagają etykietowania.
- Użyj istniejących lub nowych etykiet dla swoich obiektów. Sprawdź pliki
*_contextsaby zobaczyć, jak wcześniej oznaczano obiekty i użyj wiedzy o znaczeniu etykiet, aby przypisać nową. Najlepiej, aby była to istniejąca etykieta, która pasuje do zasad, ale czasami potrzebna jest nowa etykieta i reguły dostępu do niej. Dodaj etykiety do odpowiednich plików kontekstu. - Określ domeny i procesy, które powinny mieć własne domeny bezpieczeństwa.
Prawdopodobnie musisz napisać zupełnie nowe zasady dla każdej z nich. Na przykład wszystkie
usługi uruchamiane przez
init, powinny mieć własne zasady. Te polecenia pomagają wykryć te, które nadal działają (ale WSZYSTKIE usługi wymagają takiego traktowania):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- Sprawdź
init.device.rc, aby zidentyfikować domeny, które nie mają typu domeny. Nadaj im domenę na wczesnym etapie procesu tworzenia, aby uniknąć dodawania reguł doinitlub innego mylenia dostępuinitz dostępem, który jest objęty własnymi zasadami. - Skonfiguruj
BOARD_CONFIG.mk, aby używaćBOARD_SEPOLICY_*zmiennych. Szczegółowe informacje o konfiguracji znajdziesz w pliku README wsystem/sepolicy. - Sprawdź pliki init.device.rc i fstab.device i upewnij się, że każde użycie
mountodpowiada prawidłowo oznaczonemu systemowi plików lub że określono opcjęcontext= mount. - Sprawdź każdą odmowę i utwórz zasady SELinux, aby prawidłowo ją obsługiwać. Przykłady znajdziesz w sekcji Dostosowywanie.
Zacznij od zasad w AOSP, a następnie rozbuduj je o własne dostosowania. Więcej informacji o strategii zasad i a szczegółowe omówienie niektórych z tych kroków znajdziesz w artykule Pisanie zasad SELinux.
Przypadki użycia
Oto konkretne przykłady luk w zabezpieczeniach, które należy wziąć pod uwagę podczas tworzenia własnego oprogramowania i powiązanych z nim zasad SELinux:
Symlinki: ponieważ symlinki są widoczne jako pliki, często są odczytywane jako pliki, co może prowadzić do wykorzystania luk w zabezpieczeniach. Na przykład niektóre komponenty z uprawnieniami, takie jak init, zmieniają uprawnienia do niektórych plików, czasami na zbyt otwarte.
Hakerzy mogą następnie zastąpić te pliki symlinkami do kodu, który kontrolują, co pozwala im nadpisywać dowolne pliki. Jeśli jednak wiesz, że Twoja aplikacja nigdy nie przechodzi przez symlink, możesz zabronić jej tego za pomocą SELinux.
Pliki systemowe: rozważ klasę plików systemowych, które powinny być modyfikowane tylko przez serwer systemowy. Jednak ponieważ netd, init i vold działają jako root, mogą uzyskiwać dostęp do tych plików systemowych. Jeśli więc netd zostanie naruszony, może naruszyć te pliki i potencjalnie sam serwer systemowy.
Za pomocą SELinux możesz zidentyfikować te pliki jako pliki danych serwera systemowego.
Dlatego jedyną domeną, która ma do nich dostęp do odczytu i zapisu, jest serwer systemowy.
Nawet jeśli netd zostanie naruszony, nie będzie mógł przełączyć się na domenę serwera systemowego i uzyskać dostępu do tych plików systemowych, mimo że działa jako root.
Dane aplikacji: innym przykładem jest klasa funkcji, które muszą działać jako root, ale nie powinny mieć dostępu do danych aplikacji. Jest to niezwykle przydatne, ponieważ można tworzyć szeroko zakrojone asercje, np. zabronić niektórym domenom niezwiązanym z danymi aplikacji dostępu do internetu.
setattr: w przypadku poleceń takich jak chmod i chown możesz określić zestaw plików, w których powiązana domena może wykonywać setattr. Wszystko poza tym może być zabronione, nawet przez roota. Aplikacja może więc uruchamiać chmod i chown w przypadku plików oznaczonych jako app_data_files, ale nie shell_data_files ani system_data_files.