Co to jest VDSO i VSYSCALL?

89

Zrobiłem sudo cat /proc/1/maps -vv

Próbuję zrozumieć dane wyjściowe.Widzę, jak wiele bibliotek współdzielonych jest mapowanych na segment mapowania pamięci zgodnie z oczekiwaniami.

7f3c00137000-7f3c00179000 r-xp 00000000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00179000-7f3c00379000 ---p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00379000-7f3c0037a000 r--p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037a000-7f3c0037b000 rw-p 00043000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037b000-7f3c00383000 r-xp 00000000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00383000-7f3c00583000 ---p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00583000-7f3c00584000 r--p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00584000-7f3c00585000 rw-p 00009000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00585000-7f3c0059b000 r-xp 00000000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0059b000-7f3c0079b000 ---p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0079b000-7f3c0079c000 r--p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0

Pod koniec jest coś takiego

7f3c0165b000-7f3c0177e000 rw-p 00000000 00:00 0                          [heap]
7fff97863000-7fff97884000 rw-p 00000000 00:00 0                          [stack]
7fff97945000-7fff97946000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Co robi vdsoi vsyscallmyśli? czy vsyscall jest częścią pamięci jądra? Byłoby wspaniale, gdyby ktoś mógł rzucić trochę światła na ten problem.

liv2hak
źródło
5
Google for VDSO udostępnia tę stronę VDSO (która zawiera dalsze odniesienia).
Basile Starynkevitch
dokumentacja procfs , spójrz na wersję jądra tego pliku, aby poznać szczegóły swojego systemu.
bezartowy hałas
Myślę, że do tego tematu potrzebne jest lepsze wyjaśnienie, co można znaleźć na wiki lub w dokumentacji procfs.
Giuseppe Pes,

Odpowiedzi:

150

W vsyscall i vDSO segmenty są dwa mechanizmy stosowane w celu przyspieszenia pewnych wywołań systemowych w systemie Linux. Na przykład, gettimeofdayjest zwykle wywoływana za pośrednictwem tego mechanizmu. Pierwszym wprowadzonym mechanizmem był vsyscall , który został dodany jako sposób wykonywania określonych wywołań systemowych, które nie wymagają żadnego rzeczywistego poziomu uprawnień, aby zmniejszyć narzut wywołań systemowych. Postępując zgodnie z poprzednim przykładem, wszystko, co gettimeofdaynależy zrobić, to odczytać aktualny czas jądra. Istnieją aplikacje, które dzwonią gettimeofdayczęsto (np. W celu generowania znaczników czasu), do tego stopnia, że ​​przejmują się nawet odrobiną obciążenia. Aby rozwiązać ten problem, jądro mapuje w przestrzeni użytkownika stronę zawierającą aktualny czas i postgettimeofdayimplementacja (tj. po prostu funkcja, która odczytuje czas zapisany w vsyscall ). Korzystając z tego wirtualnego wywołania systemowego, biblioteka C może zapewnić szybkość, gettimeofdayktóra nie ma narzutu wprowadzanego przez przełączanie kontekstu między przestrzenią jądra a przestrzenią użytkownika zwykle wprowadzane przez klasyczny model wywołań systemowych INT 0x80lub SYSCALL.

Jednak ten mechanizm vsyscall ma pewne ograniczenia: przydzielona pamięć jest niewielka i dopuszcza tylko 4 wywołania systemowe, a co ważniejsze i poważniejsze, strona vsyscall jest statycznie przydzielana do tego samego adresu w każdym procesie, ponieważ lokalizacja strony vsyscall jest przybity w ABI jądra. Ta statyczna alokacja wywołania vsyscall ogranicza korzyści wynikające z randomizacji przestrzeni pamięci powszechnie używanej w systemie Linux. Osoba atakująca, po przejęciu aplikacji przez wykorzystanie przepełnienia stosu, może wywołać wywołanie systemowe z połączenia vsyscallstrona z dowolnymi parametrami. Jedyne, czego potrzebuje, to adres wywołania systemowego, który jest łatwy do przewidzenia, ponieważ jest przydzielany statycznie (jeśli spróbujesz ponownie uruchomić polecenie nawet z różnymi aplikacjami, zauważysz, że adres połączenia vsyscall się nie zmienia). Fajnie byłoby usunąć lub przynajmniej losowo zmienić lokalizację strony vsyscall, aby udaremnić tego typu atak. Niestety aplikacje zależą od istnienia i dokładnego adresu tej strony, więc nic nie można zrobić.

Ten problem bezpieczeństwa rozwiązano przez zastąpienie wszystkich instrukcji wywołań systemowych pod stałymi adresami specjalną instrukcją pułapki. Aplikacja próbująca wywołać stronę vsyscall będzie pułapka w jądrze, które następnie emuluje żądane wirtualne wywołanie systemowe w przestrzeni jądra. Rezultatem jest wywołanie systemowe jądra emulujące wywołanie systemowe wirtualne, które zostało tam umieszczone, aby w pierwszej kolejności uniknąć wywołania systemowego jądra. Wynik to wywołanie vsyscall, które trwa dłużej, ale co najważniejsze, nie przerywa istniejącego ABI. W każdym razie spowolnienie będzie widoczne tylko wtedy, gdy aplikacja spróbuje użyć strony vsyscall zamiast vDSO .

VDSO oferuje taką samą funkcjonalność jak vsyscall, przezwyciężając swoje ograniczenia. VDSO (Virtual Dynamically linked Shared Objects) to obszar pamięci przydzielony w przestrzeni użytkownika, który w bezpieczny sposób udostępnia niektóre funkcje jądra w przestrzeni użytkownika. Zostało to wprowadzone, aby rozwiązać zagrożenia bezpieczeństwa spowodowane przez vsyscall. VDSO jest przydzielane dynamicznie, co rozwiązuje problemy związane z bezpieczeństwem i może mieć więcej niż 4 wywołania systemowe. W vDSO linki są dostarczane za pośrednictwem biblioteki glibc. Linker połączy się z funkcjonalnością glibc vDSO , pod warunkiem, że taka procedura ma towarzyszącą wersję vDSO , taką jak gettimeofday. Kiedy twój program jest wykonywany, jeśli twoje jądro nie ma vDSO support, zostanie wykonane tradycyjne wywołanie systemowe.

Kredyty i przydatne linki:

Giuseppe Pes
źródło
3
Dlaczego vsyscall może mieć tylko 4 wywołania systemowe? Na wywołania systemowe zarezerwowano 8 megabajtów, a używana jest tylko 1 strona (w rzeczywistości 3 funkcje, przydzielane przez 1024 zajmują 1 stronę).
skap
9

Chcę tylko dodać, że teraz w nowych jądrach vDSOnie jest używany tylko do "bezpiecznych" wywołań systemowych, ale jest używany do decydowania, który mechanizm wywołania systemowego jest preferowaną metodą wywołania wywołania systemowego w systemie.

niekompetentny
źródło