Linux przestał działać w Hyper-V. Microsoft nie zauważył

152

Wprowadzona pod koniec 2022 roku zmiana w kernelu Linuksa sprawiła, że jądro przestało się ładować w Hyper-V. Powodem jest błędna obsługa technologii IBT. Zmiana dotarła do użytkowników z opóźnieniem, ale mimo to problem pozostał niezauważony.

Hyper-V, według oficjalnej dokumentacji Microsoftu, obsługuje tylko skromny podzbiór dystrybucji Linuksa, w większości złożony z wersji „enterprise” oraz „LTS”, w których zmiany zachodzą rzadko i powoli. Obsługa Hyper-V, dostarczana przez Microsoft, jest szeroko wdrożona w wielu innych systemach, nieobecnych na krótkiej liście w dokumentacji.

Wśród systemów, z którymi Hyper-V radzi sobie bez większych problemów są i takie, których oprogramowanie składowe jest o wiele bardziej bieżące, niż w przypadku systemów Enterprise. Do świeżo zaktualizowanych systemów, które działają z wirtualizacją Microsoftu należą między innymi Fedora oraz OpenSUSE Tumbleweed.

Problematyczny IBT

Systemy te otrzymują nowy kernel Linuksa znacznie szybciej niż np. Red Hat Enterprise Linux. Choć zawsze chodzi o wersję starszą niż upstream czystego Linuksa, jest to zdecydowanie wersja nowsza niż w systemach o przedłużonym wsparciu. Dzięki temu otrzymuje się nowości, na które w przypadku LTS trzeba czekać do następnego wydania głównego. Jedną z takich nowości było domyślne włączenie mechanizmów Intel Control-Flow Enforcement Technology, w tym rozwiązania o nazwie Indirect Branch Tracking (IBT). Obsługa IBT zadebiutowała w kernelu 5.18 i była domyślnie wyłączona aż do listopada, gdy wciągnięto do kodu zmianę domyślnego ustawienia CONFIG_X86_KERNEL_IBT. W rezultacie kernel 6.2 wzbogacił się o obsługę nowego mechanizmu bezpieczeństwa.

IBT to mechanizm wprowadzający dyscyplinę w ramach wykonywania pośrednich rozgałęzień (np. zamiast skoku do następnej instrukcji, najpierw podawany jest jej adres). Sprawa robi się istotna np. w przypadku wskaźników do funkcji. Ponieważ łatwiej jest zniekształcić adres niż samą instrukcję, istnieje potencjalne niebezpieczeństwo w postaci ukończenia rozgałęzienia w niepożądanym miejscu (i wykonania go). W przypadku intelowskiej implementacji IBT następuje weryfikacja, czy docelowe miejsce rozgałęzienia jest oznaczone jako potencjalny cel takowego (w odróżnieniu od arbitralnej lokalizacji w pamięci/rejestrze). To oczywiście nie jest stuprocentowa ochrona, ale lepsze to niż nic.

Fedora, OpenSUSE i Ubuntu w Hyper-V
Fedora, OpenSUSE i Ubuntu w Hyper-V© Licencjodawca | Kamil Dudek
Więcej od autora
1 z 169

Błąd jest w Hyper-V

Oznaczanie gałęzi przebiega z wykorzystaniem nowych instrukcji ENDBR i wymaga wspomagania sprzętowego. Hyper-V poprawnie eksponuje tę funkcjonalność procesora do maszyn… ale nie przygotowuje swoich wewnętrznych struktur (hypercall page) w sposób zgodny z IBT (niezaopatrzone w ENDBR). W rezultacie każdy hypercall kończy się niepowodzeniem. A te pochodzą z kernela i następują na bardzo wczesnym etapie uruchomienia. W rezultacie kernel Linuksa zawiesi się w Hyper-V, jeżeli jest ono uruchomione na Intelu jedenastej generacji lub nowszym. Dzieje się to tylko na kernelach z włączonym IBT, co np. w OpenSUSE nastąpiło po kernelu 6.3.2, podczas gdy Ubuntu Server 23.10 z jądrem 6.3.0 dalej działa.

Błąd bezsprzecznie znajduje się w Hyper-V. Ale to wcale nie jest oczywiste, gdy się go napotka. W konfrontacji z problemem „zmienił się kernel, ale Hyper-V nie”, doświadczenie nakazuje założyć, że nowy kernel działa nieprawidłowo, a nie że ukazał jakiś nieznany błąd w hipernadzorcy. Wychodząc z tego założenia, błąd zgłoszono nie do Hyper-V, a do kernela (autorem zgłoszenia jest autor niniejszego tekstu), początkowo zakładając, że chodzi tylko o Fedorę. Michael Kelley z Microsoftu prędko zidentyfikował, że błąd dotyczy jednak Hyper-V.

…ale poprawka będzie w kernelu

Zgłoszenia jednak nie zamknięto… ponieważ poprawka zostanie wykonana w jądrze Linuksa! Celem zapewnienia działania kernela w wadliwym Hyper-V, Linux będzie sprawdzać, czy hypercall page jest zgodny z IBT. Jeżeli nie, IBT jest wyłączane, aby korzystanie z hypercalli było możliwe. Wydaje się to być radykalnym podejściem do doktryny Torvaldsa we do not break userspace„, ale decyzja o poprawce jądrze ma też inne powody: istnieje wiele wdrożeń Linuksa na Hyper-V, które wkrótce mogą zostać zaktualizowane do nowego kernela (np. ze względów bezpieczeństwa) i przestać działać. Poprawka do Hyper-V może nadejść później niż poprawka w kernelu. Jak pisze sam Kelley, „ścieżka wdrożenia poprawek do Hyper-V jest dość długa”.

Microsoft planuje w istocie naprawić Hyper-V, ale zanim to nastąpi, problem zostanie rozwiązany po stronie Linuksa. Istnieje także obejście, w postaci uruchomienia jądra z parametrem ibt=off. Warto mieć też na uwadze fakt, że na procesorach bez IBT (i bez ENDBR64) problem po prostu nie występuje. Być może dlatego został przeoczony w Redmond…

Kamil J. Dudek, współpracownik redakcji dobreprogramy.pl

Źródło: dobreprogramy

Komentarz