2011-10-21 4 views
8

W systemie x86 mam moduł jądra Linux ("moduł obserwatora"), który otrzymuje powiadomienie przez jądro za każdym razem, gdy ładowany jest konkretny moduł jądra ("cel"). Prawie każdy moduł jądra może być celem. Używam tego w an instrumentation system Nad którym pracuję.Czy istnieje sposób, aby moduł jądra znajdował adresy sekcji innego załadowanego modułu?

Gdy moduł obserwatora obsługuje takie powiadomienie, może być wygodny z jakiegoś powodu, jeśli obserwator zna adresy sekcji ELF załadowanego modułu docelowego. Jakieś pomysły, w jaki sposób można uzyskać te informacje w przestrzeni jądra?

Oczywiście prawdopodobnie mógłbym pobrać zawartość odpowiednich plików w /sys/module/<target_name>/sections/ w przestrzeni użytkownika zaraz po załadowaniu celu, a następnie jakoś przekazać te dane do modułu obserwatora, ale jest to zbyt niezdarne. Chciałbym znaleźć sposób na uzyskanie tej informacji bezpośrednio w przestrzeni jądra.

O ile widziałem w źródłach modułu ładującego moduł, nie zapisuje on adresów sekcji w struct module, tylko tworzy pliki sysfs dla sekcji. Być może jest możliwe, aby znaleźć obiekty jądra odpowiadające tym plikom i odczytać potrzebne dane z tych obiektów? A może użyjesz innego podejścia?

+0

Wygląda na to, że kobject zawarty w 'module struct' (' mkobj.kobj' field) uczestniczy w reprezentacji modułu w sysfs. Pogłębię to jeszcze bardziej, gdy będę mieć czas. Możliwe jest uzyskanie atrybutów zawierających nazwy i adresy sekcji używających tego kobject jako punktu wyjścia. – Eugene

Odpowiedz

5

Po wykopaniu sposobu, w jaki informacja o sekcjach modułu dostaje się do sysfs, nie znalazłem sposobu na odzyskanie go bez użycia wewnętrznych definicji struktury jądra. Używanie takich rzeczy nie jest opcją w moim projekcie, więc w końcu wdrożyłem inne podejście, które, mam nadzieję, jest bardziej niezawodne.

W skrócie, pomysł jest następujący. Mój moduł jądra wykorzystuje interfejs API helpera w trybie użytkownika, aby uruchomić proces przestrzeni użytkownika (faktycznie powłoka wykonująca mój skrypt). Proces ten otrzymuje nazwę "docelowego" modułu jądra jako parametr i zbiera informacje o jego sekcjach od sysfs (/sys/module/<target_name>/sections/). Z przestrzeni użytkownika informacje te można łatwo uzyskać. Następnie przekazuje zgromadzone dane do mojego modułu jądra jako ciąg znaków przez plik w debugfs. Moduł analizuje ciąg znaków i sprawdza jego zawartość. Jeśli wszystko jest w porządku, będą dostępne nazwy i adresy początkowe sekcji ELF.

Przyznaję, że sztuczka z pomocnikiem trybu użytkownika jest dość niezręczna, ale wykonuje zadanie.

Przygotowałem przykładową implementację opisanego powyżej podejścia - patrz "Sections" example.

Szczegółowe informacje na temat API pomocnika trybu użytkownika można znaleźć w źródłach jądra pod kodem <linux/kmod.c> i <linux/kmod.h>, a mianowicie w definicji call_usermodehelper(). Przykłady oraz wyjaśnienie typowego zastosowania interfejsu API są dostępne pod adresem this article.

Należy zauważyć, że przykłady z that article są nieco niedokładne: funkcja inicjalizacyjna modułu zwraca tam wynik call_usermodehelper(). Ta ostatnia zwraca jednak kod bajtu 2-bajtowego (przynajmniej w połączeniu z UMH_WAIT_PROC) zamiast 0 lub ujemnego kodu błędu, którego funkcja init ma zwrócić. Może to spowodować ostrzeżenia o czasie pracy. To, co call_usermodehelper() faktycznie zwraca, wyjaśnił here.

1

Plik linux/kernel/module.c ma kilka niestatycznych funkcji (ale bez tego EXPORT_SYMBOL z przodu), takich jak module_address_lookup(), ale te funkcje używają rzeczy takich jak preempt_disable() i _enable(). Wolałbym nie używać tych funkcji i sugerowałbym używanie interfejsu sysfs zamiast tego, mimo że twój sterownik jest już w trybie jądra.

+0

Dziękuję za odpowiedź. Tak, wiem o 'module_address_lookup()' i tym podobne. Są używane w systemie Kallsyms do wyszukiwania symboli i tym podobnych. Ale potrzebuję innej rzeczy, adresów modułów _sections_ (.text, .devinit.text, .exit.text, itp.) Zamiast symboli. Mogę uzyskać adresy obszarów "init" i "core" modułu, ale każdy z nich może zawierać więcej niż jedną sekcję ELF. – Eugene

+0

Z kodu źródłowego programu ładującego wynika, że ​​przed wydaniem powiadomień o ładowaniu informacja o sekcjach właśnie załadowanego modułu jest dostępna tylko w systemie Sysfs. Jeśli się nie mylę, każdy plik w sysfs jest wspierany przez obiekt jądra. Jeśli masz pojęcie, w jaki sposób mój moduł mógłby znaleźć takie obiekty odpowiadające plikom w '/ sys/module/', byłoby świetnie. – Eugene

+0

Nie widzę sposobu na uzyskanie tych informacji z jądra, chyba że zmodyfikujesz jądro/moduł.c, aby wyeksportować symbol lub funkcję. Możesz spróbować wysłać łatkę z rozsądną wiadomością, dlaczego chcesz tego w ten sposób. –

Powiązane problemy