Tylko w ten sam sposób, w jaki modprobe
„pokonuje” bezpieczeństwo, ładując nowy kod do jądra.
Z różnych powodów czasem lepiej jest mieć częściowo uprzywilejowany kod (np. Sterowniki graficzne na serwerze X) działający w przestrzeni użytkownika, a nie w wątku jądra.
- Będąc w stanie to
kill
zrobić łatwiej, chyba że zablokuje HW.
- Posiadanie strony żądania kodu / danych z plików w systemie plików. (Pamięć jądra nie jest stronicowana)
- Nadanie jej własnej wirtualnej przestrzeni adresowej, w której błędy na serwerze X mogą po prostu spowodować awarię serwera X bez konieczności usuwania jądra.
Nie robi wiele dla bezpieczeństwa, ale ma wiele zalet związanych z niezawodnością i architekturą oprogramowania.
Pieczenie sterowników graficznych w jądrze może zredukować przełączanie kontekstu między klientami X a serwerem X, jak tylko jeden użytkownik-> jądro-> użytkownik, zamiast konieczności wprowadzania danych do innego procesu przestrzeni użytkowej, ale serwery X były historycznie za duże i zbyt błędne chcieć ich w pełni w jądrze.
Tak, złośliwy kod z tymi uprawnieniami może w razie potrzeby przejąć jądro, /dev/mem
modyfikując kod jądra.
Lub na przykład na x86, uruchom cli
instrukcję, aby wyłączyć przerwania na tym rdzeniu po iopl
wywołaniu systemowym, aby ustawić poziom uprawnień IO na ring 0.
Ale nawet iopl
„tylko” x86 daje dostęp do niektórych instrukcji : in / out (i wersje string in / out) oraz cli / sti. Nie pozwala używać rdmsr
ani wrmsr
odczytywać ani zapisywać „rejestrów specyficznych dla modelu” (np. IA32_LSTAR
Który ustawia adres punktu wejścia jądra dla syscall
instrukcji x86-64 ), ani nie lidt
zastępuje tablicy deskryptorów przerwań (co pozwoliłoby ci całkowicie wziąć na maszynie z istniejącego jądra, przynajmniej na tym rdzeniu.)
Nie można nawet odczytać rejestrów kontrolnych (takich jak CR3, który zawiera adres fizyczny katalogu stron najwyższego poziomu, do którego atakujący może się przydać jako przesunięcie w /dev/mem
celu zmodyfikowania własnych tabel stron jako alternatywy dla mmap
większej ilości danych /dev/mem
. )
invd
(unieważnij wszystkie pamięci podręczne bez zapisywania !! ( przypadek użycia = wczesny BIOS przed skonfigurowaniem pamięci RAM)) to kolejna zabawna, która zawsze wymaga pełnego CPL 0 (aktualny poziom uprawnień), nie tylko IOPL. Nawet wbinvd
jest uprzywilejowany, ponieważ jest tak wolny (i nie jest przerywany) i musi opróżniać wszystkie pamięci podręczne na wszystkich rdzeniach. (Patrz Czy istnieje sposób, aby wypłukać całą pamięć podręczną procesora związanych z programem? I wykorzystanie instrukcji WBINVD )
Błędy, które powodują przeskakiwanie na zły adres z działającymi danymi jako kodem, nie mogą więc przypadkowo wykonać żadnej z tych instrukcji na serwerze X w przestrzeni użytkownika.
Obecny poziom uprawnień (w trybie chronionym i długim) to niskie 2 bity cs
(selektora segmentu kodu) . mov eax, cs
/ and eax, 3
działa w dowolnym trybie, aby odczytać poziom uprawnień.
Aby napisać poziom uprawnień, wykonaj a jmp far
lub call far
ustaw CS:RIP
(ale wpis GDT / LDT dla segmentu docelowego może go ograniczyć na podstawie starego poziomu uprawnień, dlatego przestrzeń użytkownika nie może tego zrobić, aby się podnieść). Lub używasz int
lub, syscall
aby przełączyć na pierścień 0 w punkcie wejścia jądra.
iopl
nie zezwala na wszystkie uprzywilejowane instrukcje, więc nadal jest użyteczny, aby upewnić się, żeinvd
błędny program przestrzeni użytkownika nie zostanie przypadkowo uruchomiony , przeskakując przez uszkodzony wskaźnik funkcji wskazujący na wykonywalną pamięć zaczynającą się od0F 08
bajtów. Dodałem odpowiedź z niektórymi przyczynami niezwiązanymi z bezpieczeństwem, dlaczego użyteczne jest, aby procesy w przestrzeni użytkownika podniosły ich uprawnienia.