kernel

Zastosowanie KSM w maszynach wirtualnych QEMU/KVM

Użytkownicy linux'a, którzy korzystają z mechanizmu wirtualizacji QEMU/KVM, wiedzą, że takie maszyny wirtualne potrafią zjadać dość sporo pamięci operacyjnej. Im więcej takich maszyn zostanie uruchomionych w obrębie danego hosta, tym większe ryzyko, że nam tego RAM'u zwyczajnie zabraknie. Można oczywiście ratować się dokupieniem dodatkowych modułów pamięci ale też nie zawsze taki zabieg będzie możliwy, zwłaszcza w przypadku domowych stacji roboczych pokroju desktop/laptop. Szukając rozwiązania tego problemu natrafiłem na coś, co nazywa się Kernel Samepage Merging. W skrócie, KSM to mechanizm, który ma na celu współdzielenie takich samych stron pamięci operacyjnej przez kilka procesów. W ten sposób można (przynajmniej teoretycznie) dość znacznie obniżyć zużycie RAM, zwłaszcza w przypadku korzystania na maszynach wirtualnych z tych samych systemów operacyjnych. Przydałoby się zatem ocenić jak bardzo KSM wpłynie na wykorzystanie pamięci i czy będzie z niego jakiś większy użytek zarówno przy korzystaniu z maszyn wirtualnych, czy też w codziennym użytkowaniu komputera.

Konfiguracja HugePages pod maszyny wirtualne QEMU/KVM

W linux rozmiar stron pamięci operacyjnej RAM ma domyślnie 4096 bajtów (4 KiB). Maszyny wirtualne QEMU/KVM mają to do siebie, że wykorzystują dość spore zasoby pamięci (wile GiB), przez co mały rozmiar strony może niekorzystnie wpływać na wydajność systemów gościa. Chodzi generalnie o to, że rozrostowi ulega tablica stron, której przeszukiwanie jest czasochłonną operacją. By temu zaradzić, wymyślono TLB (Translation Lookaside Buffer), który ulokowany jest albo w CPU albo gdzieś pomiędzy CPU i główną pamięcią operacyjną. TLB to mały ale za to bardzo szybki cache. W przypadku systemów z duża ilością pamięci RAM, niewielki rozmiar TLB sprawia, że odpowiedzi na zapytania nie są brane z cache, tylko system wraca do przeszukiwania normalnej tablicy stron zlokalizowanej w pamięci RAM (TLB miss). Taka sytuacja jest bardzo kosztowna, spowalnia cały system i dlatego trzeba jej unikać. Na szczęście jest mechanizm HugePages, który pozwala na zwiększenie rozmiaru strony pamięci z domyślnych 4 KiB do 2 MiB lub nawet do 1 GiB w zależności od właściwości głównego procesora. W tym artykule postaramy się skonfigurować HugePages na potrzeby maszyn wirtualnych dla systemu Debian Linux.

Wirtualizacja QEMU/KVM (libvirt) na Debian Linux

Prawdopodobnie dla większości użytkowników linux'a, wirtualizacja kojarzy się w zasadzie z jednym oprogramowaniem, tj. VirtualBox. Niby strona VBox'a podaje, że jest on na licencji GPL-2 ale w Debianie nie ma go w głównym repozytorium (jest on obecny w sekcji contrib ). Problem z VirtualBox'em jest taki, że wymaga on kompilatora Open Watcom, który już wolnym oprogramowaniem nie jest. VBox też nie jest jedynym oprogramowaniem, które na linux można wykorzystać w roli hiperwizora do obsługi maszyn wirtualnych. Jest o wiele lepsze rozwiązanie, mianowicie QEMU, które jest w stanie zrobić użytek z maszyny wirtualnej kernela (Kernel Virtual Machine, KVM) i realizować dokładnie to samo zadanie, które zwykł ogarniać VirtualBox. Wirtualizacja na bazie QEMU/KVM jest w pełni OpenSource, co ucieszy pewnie fanów wolnego i otwartego oprogramowania, choć zarządzanie maszynami wirtualnymi odbywa się za sprawą konsoli. Oczywiście, osoby które korzystają z VirtualBox'a zdają sobie sprawę, że to narzędzie oferuje graficzny menadżer maszyn wirtualnych (Virtual Machine Manager, VMM), który usprawnia i znacznie ułatwia zarządzanie wirtualnymi maszynami. Jeśli GUI jest dla nas ważnym elementem środowiska pracy i nie uśmiecha nam się konfigurować maszyn wirtualnych przy pomocy terminala, to jest i dobra wiadomość dla takich osób, bo istnieje virt-manager , który jest dość rozbudowanym menadżerem maszyn wirtualnych pozwalającym na ich tworzenie, konfigurowanie i zarządzanie nimi przy wykorzystaniu graficznego interfejsu użytkownika. W tym artykule postaramy się skonfigurować naszego Debiana w taki sposób, by przygotować go do pracy z maszynami wirtualnymi posługując się qemu/libvirt/virt-manager .

Czym jest linux kernel driver binding

Bawiąc się ostatnio QEMU/KVM na swoim laptopie z zainstalowanym Debianem natrafiłem na ciekawe zagadnienie związane z wirtualizacją, tj. z PCI passthrough. Nie chodzi mi tutaj o samą technikę PCI passthrough ale o dobór sterowników do urządzeń działających pod kontrolą linux. Każdy sprzęt, który ma działać w systemie, musi mieć załadowany w pamięci RAM stosowny moduł kernela. Te moduły zwykle są ładowane automatycznie podczas pracy systemu, np. gdy podłączamy nowy sprzęt do komputera (można też te moduły ładować i ręcznie via modprobe ). Gdy nasz linux z jakiegoś powodu dobierze niewłaściwy (z naszego punktu widzenia) moduł dla jakiegoś urządzenia, to możemy to urządzenie odłączyć od komputera, a moduł bez problemu wyładować, po czym dokonać stosownych poprawek w systemie. Problem zaczyna się w sytuacji, gdy mamy do czynienia ze sprzętem, którego nie da się od komputera fizycznie odłączyć, np. wbudowana w płytę główną karta dźwiękowa, czy też wbudowana grafika bezpośrednio w CPU. Podobnie sprawa wygląda w przypadku wkompilowania modułów na stałe w kernel -- jak wyładować moduł, którego się nie da wyładować? By w takich sytuacjach zmienić przypisany urządzeniu sterownik trzeba dodać parę plików w katalogach /etc/modules-load.d/ / /etc/modprobe.d/ oraz zrestartować maszynę, tak by podczas fazy boot kernel dobrał sprzętowi pożądane przez nas moduły i ich konfigurację. Niemniej jednak, istnieje prostszy sposób na zmianę sterownika działającego w systemie sprzętu i to bez potrzeby fizycznego restartowania maszyny. Chodzi o mechanizm ręcznego przypisywania urządzeń do konkretnych sterowników (manual driver binding and unbinding).

Moduł LKRG (Linux Kernel Runtime Guard)

Jakiś czas temu opisywałem moduł TPE (Trusted Path Execution) dla kernela linux, który jest w stanie dość znacznie poprawić bezpieczeństwo naszego systemu. Ostatnio jednak natknąłem się na moduł LKRG (Linux Kernel Runtime Guard), którego to zadaniem jest stać na straży samego jądra operacyjnego i chronić je w czasie rzeczywistym przed różnego rodzaju zagrożeniami poprzez wykrywanie eksploitów wykorzystujących luki w jego mechanizmach bezpieczeństwa. Jako, że ja bardzo lubię zbroić swojego Debiana, to postanowiłem się przyjrzeć nieco bliżej temu całemu LKRG i sprawdzić jego użyteczność. Trzeba jednak wiedzieć, że LKRG jest dostarczany w formie osobnego modułu zamiast łaty na kernel, przez co trzeba będzie także postarać się o automatyzację pewnych rzeczy, m.in. procesu budowania modułu przy aktualizacji kernela via DKMS.

Jak załadować firmware karty WiFi przed initrd/initramfs

Każdy kto ma laptopa wyposażonego w kartę WiFi, czy też ogólnie komputer posiadający bezprzewodową sieciówkę, ten prawdopodobnie spotkał się z błędem podobnym do tego: Direct firmware load for iwlwifi-6000g2a-6.ucode failed with error -2 . W tym przypadku sprawa dotyczyła karty Intel Corporation Centrino Advanced-N 6205 [Taylor Peak] działającej w oparciu o moduł kernela iwlwifi . W takich przypadkach zwykle wystarczy zainstalować firmware od określonego modułu i po kłopocie. No i faktycznie w Debianie jest dostępny pakiet firmware-iwlwifi , który zawiera ten potrzebny plik iwlwifi-6000g2a-6.ucode . Problem jednak w tym, że instalacja paczki z firmware niekoniecznie może nam pomóc. Ten powyższy przykład nie jest odosobniony i czasami pliki z firmware muszą być dostępne w chwili ładowania kernela do pamięci RAM czy też na etapie initramfs/initrd. W takim przypadku zainstalowanie paczki z firmware w naszym linux'ie nic nam nie da, bo pliki rezydują na niezamontowanym jeszcze dysku. Jak zatem wybrnąć z tej wydawać by się było patowej sytuacji?

Linux kernel EFI boot stub i zaszyfrowany Debian (LUKS+LVM)

Szukając informacji na temat uruchamiania mojego zaszyfrowanego Debiana (LUKSv2+LVM) na laptopie z EFI/UEFI, natrafiłem na dość ciekawy mechanizm zwany kernel EFI boot stub, czasem też zwany kernel EFISTUB. Zadaniem tego mechanizmu jest uruchomienie linux'a bezpośrednio z poziomu firmware EFI z pominięciem czy też bez potrzeby stosowania dodatkowych menadżerów rozruchu (rEFInd) czy bootloader'ów (grub/grub2/syslinux/extlinux). Jakby nie patrzeć bardzo ciekawa alternatywa, która wymaga, by się z nią zapoznać i ocenić jej przydatność pod kątem użyteczności.

Jak przepisać linki initrd.img{,.old} i vmlinuz{,.old} z / do /boot/

Mając możliwość skonfigurowania EFI/UEFI na moim laptopie, postanowiłem jak najbardziej się za to przedsięwzięcie zabrać. Okazało się jednak, że w przypadku takiej dystrybucji linux'a jak Debian, to zadanie może być nieco problematyczne, zwłaszcza gdy chce się korzystać jedynie z menadżera rozruchu jakim jest rEFInd, czyli bez dodatkowego bootloader'a (grub/grub2/syslinux/extlinux) instalowanego bezpośrednio na dysku twardym i jednocześnie posiadając w pełni zaszyfrowany system (LUKSv2 + LVM). Rzecz w tym, że w takiej sytuacji w konfiguracji rEFInd trzeba podawać ścieżki bezpośrednio do plików initrd.img oraz vmlinuz (obecnych na partycji /boot/ ). W Debianie nazwy tych plików mają format initrd.img-x.x.x-x-amd64 i vmlinuz-x.x.x-x-amd64 . Za każdym razem, gdy wypuszczany jest nowy kernel, to ten numerek ( x.x.x-x ) ulega zmianie, co pociąga za sobą potrzebę ręcznego dostosowania konfiguracji rEFInd. Może i aktualizacje kernela w Debianie nie są jakoś stosunkowo częste ale może istnieje sposób, by ten problem z dostosowaniem konfiguracji rozwiązać?

Moduł TPE (Trusted Path Execution) dla kernela linux

Użytkownicy linux'a są zwykle chronieni przez mechanizmy bezpieczeństwa, które ten system jest w stanie zaoferować. Oczywiście deweloperzy różnych dystrybucji, np. Debiana, dokładają wszelkich możliwych starań, by system jako całość był wstępnie skonfigurowany tak, by końcowy użytkownik nie musiał za wiele majstrować przy zabezpieczeniach i mógł się czuć i być (przynajmniej względnie) bezpieczny. No i faktycznie złowrogie oprogramowanie ma czasem spore problemy dostać się do maszyny, którą operuje linux. Niemniej jednak, gdy już taki syf się do systemu dostanie, to zwykle niewiele dzieli go od przejęcia kontroli nad komputerem. Może i część zabezpieczeń linux'a zadziała i sprawi, że taki wirus/trojan czy nawet zwykły skrypt będzie miał ograniczone pole manewru, to i tak będzie on mógł przeprowadzić te akcje, które zwyczajny użytkownik systemu (nie root) jest zwykle w stanie poczynić, np. odebrać dźwięk i video ze stosownych urządzeń i przesłać te dane przez sieć. My z kolei możemy nawet tego faktu nie być świadomi. Jasne, że powinno się zwracać uwagę na to jakie pliki się pobiera z internetu i nie uruchamiać wszystkiego lekkomyślnie ale też trzeba mieć na uwadze fakt, że często jedna maszyna jest współdzielona, np. z członkami rodziny i oni już niekoniecznie muszą władać zaawansowaną wiedza z zakresu IT, by przewidzieć wszystkie możliwe zagrożenia czyhające na nich w sieci. Można za to postarać się, by uczynić naszą maszynę nieco bardziej odporną na niezbyt przemyślane zachowania użytkowników jej systemu operacyjnego. Jednym z kroków, które możemy podjąć, jest wdrożenie mechanizmu Trusted Path Execution (TPE), który póki co jest dostępny jedynie w formie patch'a na kernel linux'a lub też jako jego osobny moduł oferujący sporo więcej możliwości w stosunku do wspomnianej wcześniej łaty. W niniejszym artykule rzucimy sobie okiem na ten cały mechanizm TPE i zobaczymy jak jest on w stanie uchronić nasz OS przed niezbyt zaawansowaną ludzką inteligencją.

Jak na Debianie zrobić pakiet .deb zawierający moduł kernela linux (DKMS)

Kernel linux'a jest dość złożonym organizmem, który może zostać rozbudowany przy pomocy dodatkowego kodu ładowanego w postaci zewnętrznych modułów. Czasem ze względu na wczesny etap prac nad nową funkcjonalnością jądra, taki moduł może zachowywać się dość nieprzewidywalnie, co przekreśla jego szanse na pojawienie się w stabilnych wydaniach kernela. Czasem też z jakiegoś niezrozumiałego powodu pewne rzeczy nie są celowo dodawane do jądra operacyjnego. Jedną z nich jest moduł Trusted Path Execution (TPE), który jest w stanie znacznie poprawić bezpieczeństwo systemu uniemożliwiając przeprowadzenie w nim szeregu podejrzanych działań. W Debianie tego typu niedogodności związane z brakiem pewnych modułów można obejść przez zastosowanie mechanizmu DKMS, który przy instalacji modułu spoza głównego drzewa kernela linux'a jest nam go w stanie automatycznie zbudować. W repozytorium dystrybucji Debiana znajduje się już szereg pakietów z modułami (mają końcówki -dkms ) i w prosty sposób można je sobie doinstalować. Co jednak w przypadku, gdy mamy moduł, którego nikt jeszcze nie przygotował i nie wrzucił do repozytorium? Co, gdy takich modułów mamy kilka, a przy tym korzystamy z najnowszego stabilnego kernela, który jest aktualizowany średnio co kilka dni? Ręczna budowa wszystkich zewnętrznych modułów za każdym razem jak tylko wyjdzie nowsza wersja kernela, to nie najlepsze wyjście, zwłaszcza jak dojdzie nam do tego aktualizacja samych modułów. Można za to zrobić sobie paczkę .deb tak, by przy instalacji nowego jądra operacyjnego, system nam automatycznie zbudował wszystkie dodatkowe moduły, których nasz komputer wymaga do poprawnej pracy.