Zobaczmy co w kwestii bezpieczeństwa przyniósł najnowszy kernel, wydany w sierpniu 2020 roku.
Branch Target Identification
Dave Martin dodał obsługę instrukcji Branch Target Instructions (BTI) dla ARMv8.5, które są włączane w userspace podczas execve()
i przez cały czas dostępne z poziomu jądra. Ta modyfikacja wymagała od jej autora ręcznego „obrobienia” wielu linii kodu innego niż C, takiego jak assembler czy JIT. Ale dzięki temu tzw. Jump-Oriented Programming (JOP) nie jest już dostępny dla atakującego. Kod atakującego musi wykonywać bezpośrednie wywołania funkcji. Zasadniczo ogranicza to „użyteczny” kod dostępny dla atakującego z każdego słowa w tekście jądra do samych tylko deklaracji funkcji (lub celów owego skoku, jumpa). Jest to taka quasi-implementacja czegoś co nazywa się Control Flow Integrity (CFI). Nie jest to jeszcze pełne CFI ale też jest ważne (ponieważ znacznie zmniejsza liczbę potencjalnych celów, które można wykorzystać w ataku) i tanie (zaimplementowane sprzętowo). To dobry pierwszy krok do silnego CFI, ale nie można też tego demonizować – odpowiednio zmotywowany napastnik będzie nadal mógł skutecznie znaleźć lukę. Taki pełny CFI o wysokiej szczegółowości nie jest póki co funkcją obsługiwaną sprzętowo, ale wersja software’owa pojawi się w przyszłości w ramach implementacji CFI firmy Clang .
arm64 Shadow Call Stack
Z kolei Sami Tolvanenowi zawdzięczamy implementację w jądrze Clang’s Shadow Call Stack (SCS). Ta technologia chroni z kolei kernela przed atakami zorientowanym na Return-Oriented Programming (ROP). Ochrona jest realizowana przez utrzymywanie drugiego dedykowanego rejestru wskaźnika stosu (x18) i przechowywanie kopii adresów powrotnych w oddzielnym stosie, takim „stosie-cieniu” (stąd naturalnie nazwa). W ten sposób manipulowanie adresami zwrotnymi zwykłego stosu nie przyniesie żadnego efektu.
Warto zauważyć, że w przeciwieństwie do BTI (które jest oparta na zabezpieczeniu sprzętowym), jest to ochrona programowa, która opiera się na zlokalizowaniu tego stosu-cienia w niejawnym miejscu w pamięci. Chodzi o to aby pamięć stosu-cienia nie mogła być zapisywana bezpośrednio przez atakującego. Na przykład sprzętowa ochrona ROP firmy Intel (CET) korzysta ze sprzętowego stosu-cienia, którego nie można bezpośrednio zapisywać.
Dodano infrastrukturę Kernel Concurrency Sanitizer
Mamy też wsparcie dla Kernel Concurrency Sanitizer, czyli nowej infrastruktury do wyszukiwania data races w jądrze, za pośrednictwem CONFIG_KCSAN
. To pozwoliło na niemal natychmiastowe wykrycie nowych błędów w jądrze - niektóre ich poprawki też już zostały od razu zaimplementowane do kernela 5.8. Więcej informacji znajdziesz w dokumentacji KCSAN.
Nowe możliwości
Kernel zyskał też CAP_PERFMON
, który został zaprojektowany, aby umożliwić dostęp do perf()
. Chodzi o to, żeby dać procesowi dostęp tylko do odczytu pewnych aspektów działającego jądra i systemu. Nie będzie już potrzebne udzielanie procesom dostępu poprzez znacznie potężniejsze możliwości CAP_SYS_ADMIN
, który daje wiele możliwości zmiany wewnętrznych parametrów jądra. Pozwala to na rozdzielenie kontroli nad poufnością jądra (dostęp do odczytu przez CAP_PERFMON
) od kontroli nad integralnością (dostęp do zapisu przez CAP_SYS_ADMIN
).
Sprawdź oferty pracy na TeamQuest
Wiąże się z tym nowy CAP_BPF
, który ma na celu oddzielenie dostępu BPF od zbyt wszechmocnego CAP_SYS_ADMIN
. Został on zaprojektowany do użytku w połączeniu z CAP_PERFMON
(śledzenie) i CAP_NET_ADMIN
(działania związane z siecią). W przypadku rzeczy, które mogą zmienić integralność jądra (np. dostęp do zapisu), nadal wymagany jest CAP_SYS_ADMIN
.
Ulepszenia sieciowego generatora liczb losowych
Willy’emu Tarreau zawdzięczamy, że generator liczb losowych dla zastosowań sieciowych jest teraz mniej przewidywalny. To pozwala mieć większą nadzieję na udaremnienie prób atakującego podejmowanych aby odzyskać stan RNG, co może prowadzić do przechwycenia sesji sieciowych (poprzez prawidłowe odgadywanie stanów pakietów).