...

Wykrywanie i analiza wycieków pamięci jądra za pomocą narzędzia kmemleak

Za pomocą narzędzia kmemleak można wyszukiwać w jądrze systemu Linux obiekty pamięci, które mogą być już niedostępne. Wynik wyszukiwania to Przypadek podejrzany, brak potwierdzonego wycieku; pusty wynik również nie wyklucza błędów. Aby przeprowadzić rzetelną analizę, należy najpierw zabezpieczyć stan początkowy, wykonać ograniczony przebieg na zatwierdzonym systemie testowym i porównać wyniki po zakończeniu skanowania. Następnie należy sprawdzić w kodzie, kto jest właścicielem obiektu i kto powinien go udostępnić.

Co wykrywa kmemleak w jądrze

Kmemleak wspiera debugowanie jądra systemu Linux poprzez wyszukiwanie potencjalnie osieroconych obiektów pamięci. W tym celu śledzi obsługiwane alokacje i sprawdza, czy w skanowanych obszarach pamięci można wykryć odwołania do tych obiektów. Obiekt, który nie został rozpoznany jako dostępny, pojawia się jako potencjalny wyciek, a nie jako ostatecznie potwierdzony błąd.

Wyobraź sobie, że moduł jądra rezerwuje obiekt, a następnie traci ostatnie odwołanie do niego, nie zwalniając pamięci. Jeśli kmemleak podczas swojej Wyszukiwanie referencji Jeśli nie ma już żadnego odniesienia do tego obiektu, może go zgłosić jako podejrzany. Zgłoszenie to stanowi punkt wyjścia do zbadania alokacji i przewidywanego cyklu życia w kodzie.

Procedura ta przypomina wyszukiwanie dostępności stosowane przez moduł czyszczący pamięć (garbage collector), jednak nie przejmuje jego funkcji czyszczenia: Kmemleak nie zwalnia zgłoszonych obiektów i nie naprawia kodu. To, czy obiekt rzeczywiście został utracony, należy ustalić na podstawie jego wykorzystania, struktury własnościowej oraz przewidzianego sposobu zwolnienia.

Wyciek z jądra dotyczy pamięci zarządzanej przez kod jądra lub moduł. Wyciek w usłudze PHP lub innym procesie przestrzeni użytkownika stanowi odrębną kategorię błędów; narzędzie kmemleak nie bada jego sterty. W szerszym Wykrywanie wycieków pamięci w środowisku hostingowym W związku z tym warto rozważyć również dane procesowe i inne narzędzia diagnostyczne.

Sam wzrost wykorzystania pamięci RAM nie świadczy o Wyciek pamięci ani jego lokalizacja. Również zmiana zakresu prac lub dłuższe przechowywanie danych mogą wpływać na te potrzeby. Sensownym punktem wyjścia jest zatem proces, który można ograniczyć pod względem czasowym i funkcjonalnym, a który pozwala na ukierunkowane zbadanie podejrzeń dotyczących jądra systemu.

Dlaczego zgłoszenia pozostają przypadkami podejrzanymi

Wyszukiwanie wartości wskaźników nie jest w stanie rozpoznać wszystkich znaczeń, jakie program nadaje odwołaniom. Jeśli prawidłowe odwołanie znajduje się poza skanowanymi obszarami lub jest zapisane w sposób uniemożliwiający jego rozpoznanie przez kmemleak, obiekt, który jest nadal potrzebny, może zostać uznany za osierocony. Jest to jedna z możliwych Fałszywy alarm: Samo zgłoszenie nie stanowi dowodu na brak zezwolenia.

Możliwe jest również odwrotne zjawisko. Wartość liczbowa może przypadkowo wyglądać jak wskaźnik do obiektu, mimo że kod nie wykorzystuje jej jako odwołania. Kmemleak może wówczas uznać ten obiekt za dostępny i przeoczyć rzeczywisty wyciek. Pusty wynik nie jest zatem dowodem na to, że badany kod jest wolny od błędów.

Do tego dochodzi zakres alokacji, które są przedmiotem analizy: bezpośrednie alokacje stron oraz ioremap zgodnie z dokumentacją jądra nie są monitorowane. Osoba, która podejrzewa wzrost zużycia pamięci w tych obszarach, nie może na podstawie niepozornego raportu kmemleak wyciągnąć wniosku, że dana przyczyna nie stanowi zagrożenia. W tym celu konieczne jest przeprowadzenie innego rodzaju analizy.

Die Dostępność Jest to zatem heurystyka techniczna, a nie pełna analiza semantyczna programu. Nie daje ona wiarygodnej odpowiedzi na pytanie, czy wykryte odwołanie jest wykorzystywane w sposób sensowny, czy też pominięte odwołanie rzeczywiście brakuje. Pojedyncze wykrycie stanowi zadanie sprawdzające; brak wykryć ogranicza jedynie znaczenie danego skanowania.

W celu oceny warto ponownie wywołać podejrzenie w kontrolowanych warunkach, a następnie przeanalizować odpowiednią ścieżkę kodu. W szczególności należy wyjaśnić, kto jest właścicielem obiektu i kiedy powinien on zostać zwolniony. Tylko taka analiza może dostarczyć wiarygodnego wyjaśnienia dla stwierdzonego zjawiska.

Sprawdź środowisko testowe i wymagania

Dokumentacja z numerami wersji dla systemu Linux 6.6 stanowi tutaj podstawę merytoryczną. To, czy narzędzie kmemleak jest faktycznie dostępne w Twoim systemie, zależy jednak od używanej kompilacji jądra i jego konfiguracji, a nie wyłącznie od numeru wersji. Należy zatem sprawdzić konkretne jądro dystrybucji, które zostało zainstalowane, i zapisać informacje o kompilacji oraz konfiguracji na potrzeby późniejszej analizy.

Warunkiem jest skompilowana opcja jądra CONFIG_DEBUG_KMEMLEAK. Niezależnie od tego jest Aktywacja w czasie wykonywania: Czy jądro jest skompilowane z CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF po skonfigurowaniu można ustawić parametr rozruchowy kmemleak=on może być konieczne. Należy wyraźnie uwzględnić planowane zmiany w procesie uruchamiania dla zatwierdzonej konfiguracji testowej.

Aby uzyskać dostęp do interfejsu diagnostycznego, należy ponadto debugfs muszą być dostępne i odpowiednio zintegrowane. Konfiguracja jądra, aktywacja i dostęp do systemu plików to różne punkty kontrolne: sam brak interfejsu nie wskazuje jeszcze, który z nich jest przyczyną. Dostęp może wymagać uprawnień uprzywilejowanych.

W miarę możliwości korzystaj z izolowanej maszyny wirtualnej lub dedykowanego systemu testowego i uzyskaj wcześniej zgodę na wprowadzanie zmian. Kmemleak powoduje dodatkowe obciążenie związane z alokacją i zwolnieniem pamięci; jego wpływ zależy od środowiska i obciążenia. Bez odpowiednich pomiarów nie można podać ogólnej wartości spadku wydajności.

Wygenerowany przez sztuczną inteligencję obraz symboliczny przedstawiający mały komputer na stole warsztatowym jako dedykowany system testowania jądra.
Ilustracja wygenerowana przez sztuczną inteligencję: dedykowany system testowy zapewnia ściśle określone ramy diagnostyczne.

Oprócz jądra należy również udokumentować badany moduł, planowany przebieg oraz moment wystąpienia błędu. Raporty diagnostyczne mogą zawierać adresy wewnętrzne i inne poufne informacje. Należy je przechowywać w miejscu o ograniczonym dostępie i przed przekazaniem sprawdzić, które dane są faktycznie niezbędne do analizy błędu.

Interfejs i polecenia diagnostyczne

Na udostępnionym systemie testowym zacznij od dostępu w trybie odczytu do /sys/kernel/debug/kmemleak. Plik zawiera aktualnie zgłoszone podejrzane przypadki. Dostęp do niego może wymagać uprawnień administratora; pusty wynik opisuje jedynie widoczny stan diagnostyczny i nie stanowi dowodu na to, że jądro jest wolne od wycieków pamięci.

Wprowadź poniższe polecenie w powłoce z odpowiednimi uprawnieniami do odczytu. Nie zmienia ono stanu diagnostycznego i nadaje się również do zapisania wstępnych wyników przed podjęciem dalszych kroków.

Terminal
cat /sys/kernel/debug/kmemleak

Jeśli plik nie istnieje, należy rozważyć trzy możliwe przyczyny: jądro mogło zostać skompilowane bez CONFIG_DEBUG_KMEMLEAK Zostało skompilowane, ale kmemleak nie jest włączony w czasie wykonywania lub debugfs nie jest zamontowany w oczekiwanym miejscu. Sam brak pliku nie pozwala ustalić, która z tych sytuacji ma miejsce. Dlatego należy osobno sprawdzić konfigurację kompilacji, konfigurację rozruchu oraz zamontowanie.

Dostęp do interfejsu kmemleak
DostępCelZmiana stanu i ostrożność
cat /sys/kernel/debug/kmemleakPrzeczytaj o widocznych przypadkach budzących podejrzeniaUwaga: dokument może zawierać poufne dane diagnostyczne.
echo scan > /sys/kernel/debug/kmemleakUruchom skanowanieUprawnienia do zapisu; może modyfikować widoczną listę wyników badań.
echo clear > /sys/kernel/debug/kmemleakPobierz aktualne zgłoszenia z widocznej listy podejrzanych przypadkówDostęp do zapisu; należy wcześniej zapisać wyniki badań, pamięć nie zostanie zwolniona.

W tabeli celowo wprowadzono rozróżnienie między czytaniem a Uprawnienia do zapisu: Skanowanie i czyszczenie widocznej listy powodują zmianę stanu diagnostycznego. Również ewentualne zamontowanie partycji debugfs powoduje zmiany w systemie. Czynności te należy wykonywać wyłącznie po uzyskaniu zgody i odpowiednich uprawnień; przekierowanie poleceń zapisu również wymaga odpowiednich uprawnień.

Powtarzalne zawężanie kręgu podejrzanych przypadków

Najpierw zapisz pełny wydruk interfejsu wraz z datą i godziną, wersją jądra oraz konfiguracją testową. Istniejące już komunikaty należą do Wyniki badań wstępnych i nie wolno ich bez porównania przypisywać do poniższego testu. Przechowuj wydruk w bezpiecznym miejscu, ponieważ może on zawierać adresy wewnętrzne i inne informacje diagnostyczne.

W udostępnionym systemie testowym możesz następnie usunąć aktualnie widoczne komunikaty z listy podejrzanych za pomocą poniższego polecenia powłoki. Powłoka wymaga uprawnień do zapisu w interfejsie. Polecenie to nie zwalnia bloków pamięci ani nie usuwa przyczyny; bez uprzedniego utworzenia kopii zapasowej ważne informacje mogą zostać utracone.

Terminal
echo clear > /sys/kernel/debug/kmemleak

Następnie uruchom proces o możliwie wąskim zakresie i dobrze udokumentowany, na przykład inicjalizację i kontrolowane czyszczenie modułu, który ma zostać zbadany. Należy odnotować, jakie kroki zostały wykonane i kiedy zostały zakończone. Dzięki temu późniejsze odkrycie będzie można bardziej konkretnie porównać z przebiegiem procesu, bez tego, by sama bliskość czasowa stanowiła dowód związku przyczynowego.

Po upływie czasu uruchom skanowanie w odpowiednio uprawnionej powłoce, a następnie ponownie odczytaj interfejs. Oba polecenia wymagają, aby kmemleak był aktywny, a interfejs debugfs był dostępny.

Terminal
echo scan > /sys/kernel/debug/kmemleak
cat /sys/kernel/debug/kmemleak

Powtórz procedurę w sposób kontrolowany i daj jej wystarczająco dużo czasu. Skanowanie nie musi od razu dostarczyć powtarzalnych wyników. W celu wykrycia regresji porównaj ten sam test przed i po zmianie kodu, przy możliwie identycznej konfiguracji jądra i obciążeniu; udokumentuj pozostałe różnice. Nowe podejrzenie potwierdza hipotezę, ale nie zastępuje sprawdzenia cyklu życia obiektu.

Test modułu i ocena wyników

Podczas testu modułu możesz na przykład wykonać ścieżkę inicjalizacji, a następnie przejść przez przewidzianą ścieżkę sprzątania. Jeśli po tym pojawi się nowy wpis, należy najpierw zanotować rozmiar obiektu, jego wiek i kontekst procesu, a także powiązane kroki testowe. Dane te pomagają w przyporządkowaniu wyników; same w sobie nie wskazują jeszcze, czy obiekt rzeczywiście powinien był zostać zwolniony.

Der Ślad stosu alokacji prowadzi do miejsca, w którym zgłoszono żądanie przydzielenia pamięci. Stamtąd możesz prześledzić w kodzie, kto przejmuje obiekt i jaką ścieżką powinien go zwolnić. Ślad nie musi zawierać miejsca, w którym nie doszło do zwolnienia pamięci: przydzielenie pamięci i pominięcie jej zwolnienia mogą mieć miejsce w różnych funkcjach.

Weź również pod uwagę Kolejność alokacji: Dokumentacja opisuje wyniki w tej kolejności. Wcześniejszy, osierocony obiekt może powodować pojawienie się kolejnych komunikatów. Dlatego przed uznaniem ich za niezależne usterki sprawdź, czy kilka wpisów dotyczy tego samego zespołu obiektów lub ścieżki błędu.

W celu przeprowadzenia opcjonalnego testu działania w aktualnej dokumentacji jądra opisano moduł kmemleak-test, który celowo powoduje wycieki pamięci. Należy go używać wyłącznie w izolowanym środowisku testowym i wcześniej sprawdzić, czy jest on dostępny w danym jądrze oraz czy jest odpowiednio skonfigurowany. Aktualna dokumentacja nie gwarantuje jego dostępności dla każdego starszego jądra lub jądra specyficznego dla danej dystrybucji.

Również w przypadku tego modułu diagnostycznego nie ma gwarancji natychmiastowego komunikatu lub trafienia już przy pierwszym skanowaniu. Zanotuj czas przeprowadzenia testu oraz kolejność skanowania i powtórz badanie w kontrolowany sposób. Jeśli wynik początkowo pozostaje pusty, sprawdź warunki wstępne i przebieg procedury, zamiast wyciągać wnioski wyłącznie na podstawie tego, czy środowisko diagnostyczne działa prawidłowo, czy jest uszkodzone.

Sprawdzić przyczynę zamiast ukrywać komunikat

W przypadku podejrzenia błędu zacznij od cyklu życia zgłoszonego obiektu: jaką funkcję rezerwuje, kto następnie przejmuje za niego odpowiedzialność i kiedy ma zostać zwolniony? Ślad stosu alokacji doprowadzi cię do źródła rezerwacji. To, czy błąd występuje właśnie tam, czy też w późniejszym miejscu, można ocenić dopiero na podstawie ścieżki kodu.

Zwróć szczególną uwagę na Struktura własnościowa przy przekazywaniu danych między funkcjami i modułami. Jeśli przekazywane jest odwołanie, musi być jasne, która strona je zachowuje, a która strona dokonuje zwolnienia pamięci. Należy również porównać standardową ścieżkę sprzątania z ścieżkami przerwania i błędów, na przykład gdy inicjalizacja zostanie zakończona tylko częściowo.

Ilustracja wygenerowana przez sztuczną inteligencję, przedstawiająca połączone kształty i przerwany pasek jako symbol odniesienia, które ma zostać sprawdzone.
Ilustracja wygenerowana przez sztuczną inteligencję: Sprawdzenie cyklu życia obiektu pozwala ustalić, czy odniesienie rzeczywiście zostało utracone.

Komunikat może pojawić się nawet wtedy, gdy istnieje prawidłowe odwołanie, którego kmemleak nie rozpoznaje. Zanim więc go zignorujesz, sprawdź, gdzie i w jakiej postaci przechowywany jest wskaźnik. Udokumentuj, dlaczego obiekt pozostaje dostępny przez cały przewidziany okres życia oraz w jaki sposób zostaje ostatecznie zwolniony.

W przypadku sprawdzonych przypadków szczególnych programiści mają do dyspozycji Adnotacje do dyspozycji: kmemleak_not_leak oznacza znany obiekt jako niebędący wyciekiem, ale nadal pozwala na skanowanie go pod kątem odwołań. kmemleak_ignore wyklucza ten obiekt zarówno z komunikatu, jak i ze skanowania. W związku z tym w analizie mogą brakować zawarte w nim odniesienia.

Sprawdź dostępność i semantykę API w faktycznie używanym jądrze; aktualna dokumentacja API nie gwarantuje automatycznie zgodności z każdą starszą kompilacją. Adnotacja nie rozwiązuje problemu ani brakującej autoryzacji, ani błędnej zmiany właściciela. Nie należy jej zatem stosować wyłącznie w celu usunięcia niepożądanego wyniku.

Wykrywanie usterek i bezpieczna eksploatacja

Brak pliku /sys/kernel/debug/kmemleak, najpierw sprawdź, która kompilacja jądra została faktycznie uruchomiona oraz jej konfigurację. CONFIG_DEBUG_KMEMLEAK musi być dostępny; sam numer wersji dystrybucji nie wystarczy. Zapisz informacje o kompilacji i konfiguracji, aby późniejsze porównania odbywały się na tej samej podstawie.

Osobno sprawdź Aktywacja w czasie wykonywania oraz włączenie debugfs. W przypadku CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF parametr rozruchowy może kmemleak=on może być konieczne. Brakujący plik sam w sobie nie pozwala rozróżnić tych potencjalnych przyczyn; zmiany w procesie rozruchu lub zamontowanie partycji debugfs powinny być wprowadzane w zatwierdzonej konfiguracji testowej.

Jeśli wynik po teście jest pusty, sprawdź, czy badany przebieg rzeczywiście został wykonany i czy między przebiegiem a skanowaniem upłynęło wystarczająco dużo czasu. Powtórz test w udokumentowanych warunkach i porównaj wyniki z zapisanym wynikiem początkowym. Nawet wtedy pusty raport ma ograniczoną wartość: kmemleak nie rejestruje każdej alokacji ani każdego istotnego odwołania.

Zabezpiecz istniejące wyniki przed zmianami stanu diagnostycznego. Wyniki mogą zawierać adresy wewnętrzne i inne poufne informacje; postępuj z nimi zgodnie z zasadami dostępu i publikacji obowiązującymi w Twoim środowisku. Czynności powodujące zmianę stanu należy w miarę możliwości wykonywać na odizolowanym, udostępnionym systemie testowym i uwzględnić dodatkowy nakład pracy związany z diagnostyką, nie przyjmując przy tym nieuzasadnionej wartości procentowej.

Duże zapotrzebowanie na pamięć lub Obciążenie pamięci stanowi odrębny problem operacyjny i sam w sobie nie stanowi dowodu na istnienie luki w jądrze systemu. W ocenie czasów oczekiwania i niedoboru pamięci pomocny jest artykuł na temat Obciążenie pamięci w jądrze systemu Linux. Należy połączyć takie obserwacje pracy z ukierunkowaną analizą kodów błędów i wyników diagnostycznych, zamiast wyciągać wnioski co do przyczyny bezpośrednio na podstawie krzywej RAM.

Wybór odpowiedniego narzędzia diagnostycznego

Wybierz narzędzie zgodnie z przypuszczalną Klasa błędów, a nie wyłącznie na podstawie ogólnego objawu rosnącego zużycia pamięci. kmemleak wyszukuje potencjalnie osierocone, obsługiwane obiekty jądra. W przypadku nieprawidłowych dostępów lub problemów z pamięcią w procesie użytkownika wskazane jest zastosowanie innego narzędzia; narzędzia te służą do rozwiązywania różnych problemów.

Narzędzia diagnostyczne według obszaru zastosowania i problemu
NarzędzieZakres zastosowaniaTypowe pytania
kmemleakJądro LinuxCzy jest możliwe, że do śledzonych obiektów nie ma już żadnych odwołań?
KAZANJądro LinuxCzy występują nieprawidłowe operacje dostępu do pamięci, takie jak dostęp poza granicami lub wykorzystanie po zwolnieniu pamięci?
KFENCEJądro LinuxCzy przy zastosowaniu innych narzędzi diagnostycznych występują określone błędy pamięci?
Valgrind MemcheckPrzestrzeń użytkownikaCzy w programie użytkownika występują błędy pamięci lub potencjalne wycieki?

Podejrzenie utraty odwołania do jądra wskazuje w pierwszej kolejności na kmemleak. Jeśli natomiast obraz błędu wskazuje na dostęp poza obiektem lub do pamięci już zwolnionej, do analizy tej klasy nadaje się KASAN. KFENCE również śledzi określone błędy pamięci, ale stosuje inne podejście do instrumentacji; dostępność i przydatność zależą od konkretnego jądra i środowiska testowego.

Jeśli podejrzenia dotyczą procesu w przestrzeni użytkownika, należy zbadać jego pamięć za pomocą odpowiedniego narzędzia, takiego jak Valgrind Memcheck. Raport kmemleak dotyczący obiektów jądra nie zastępuje analizy sterty aplikacji. Z drugiej strony, wskazówka pochodząca z procesu użytkownika nie wyjaśnia automatycznie, czy moduł jądra traci pamięć.

W celu kontynuowania pracy wybierz jeden z poniższych test, który można powtórzyć i zapisz proces kompilacji jądra, konfigurację oraz przebieg operacji. Zbadaj zgłoszony cykl życia obiektu w kodzie, usuń wykrytą przyczynę i powtórz ten sam przebieg w możliwie identycznych warunkach. Ponownie porównaj wyniki; sam brak komunikatu nie świadczy jeszcze o całkowitej bezbłędności.

Źródła i aktualny stan wiedzy

Stan badań:

Podstawą merytoryczną jest dokumentacja systemu Linux 6.6. Należy sprawdzić, czy uzupełnienia pochodzące z aktualnej dokumentacji oraz dostępność interfejsu API mają zastosowanie do faktycznie używanego jądra; stan na dzień 4 listopada 2026 r.

https://kernel.org/doc/html/v6.6/dev-tools/kmemleak.html

https://www.kernel.org/doc/html/latest/dev-tools/kmemleak.html

https://cdn.kernel.org/doc/html/latest/core-api/mm-api.html

https://cdn.kernel.org/doc/html/latest/dev-tools/testing-overview.html

Artykuły bieżące