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 vdso
i vsyscall
myśli? czy vsyscall jest częścią pamięci jądra? Byłoby wspaniale, gdyby ktoś mógł rzucić trochę światła na ten problem.
Odpowiedzi:
W vsyscall i vDSO segmenty są dwa mechanizmy stosowane w celu przyspieszenia pewnych wywołań systemowych w systemie Linux. Na przykład,
gettimeofday
jest 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, cogettimeofday
należy zrobić, to odczytać aktualny czas jądra. Istnieją aplikacje, które dzwoniągettimeofday
czę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 postgettimeofday
implementacja (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ść,gettimeofday
któ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ń systemowychINT 0x80
lubSYSCALL
.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ą jakgettimeofday
. 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:
źródło
Chcę tylko dodać, że teraz w nowych jądrach
vDSO
nie 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.źródło