Wywołania systemowe obsługiwane przy uruchamianiu jądra

9

Czy istnieje sposób na uzyskanie liczby lub listy wywołań systemowych obsługiwanych przez aktualnie działające jądro Linuksa? Chcę więc znaleźć sposób na „odczytanie” tabeli syscall działającego jądra.

Swair
źródło

Odpowiedzi:

15

Plik /proc/kallsymszawiera wszystkie symbole działającego jądra. Zgodnie z konwencją wywołania systemowe mają nazwy zaczynające się od sys_. W systemie 64-bitowym wywołania systemowe programów 32-bitowych zaczynają się od sys32_. Ściśle mówiąc, zawiera listę wewnętrznych funkcji jądra, a nie wywołania systemowego, ale myślę, że korespondencja działa (każde wywołanie systemowe wywołuje funkcję wewnętrznego jądra w celu wykonania zadania i myślę, że nazwa jest zawsze nazwą wywołania systemowego z sys_dopisanym ).

</proc/kallsyms sed -n 's/.* sys_//p'

Zwykle nie jest to użyteczna informacja, ponieważ wywołania systemowe zmieniają się bardzo powoli. Opcjonalne komponenty zapewniają funkcjonalność w zakresie istniejących wywołań systemowych, wykorzystując ogólne funkcje, takie jak urządzenia (z ioctl, kiedy readi writenie wycina go), systemy plików, gniazda itp. Określenie listy obsługiwanych wywołań systemowych nie powie nic na temat funkcji obsługiwany przez system. Inne wewnętrzne nazwy funkcji również nie pomogą, ponieważ zmieniają się bardzo szybko: nazwa funkcji, która implementuje niektóre funkcje w jednej wersji jądra, może ulec zmianie w następnej wersji.

Gilles „SO- przestań być zły”
źródło
+1. Właśnie to miałem na myśli, mówiąc „Pozwolę, aby ktoś z większym doświadczeniem niż ja odpowiedział” . Ponadto, ponieważ /proc/kallsymsmożna nim manipulować jak każdym innym plikiem, korzystanie z niego w programie staje się dość łatwe.
John WH Smith
2
@JohnWHSmith „Można nim manipulować jak każdy inny plik”… z zastrzeżeniem, że w systemach z jądrem ASLR ten plik powinien być odczytywalny tylko przez root.
Gilles „SO- przestań być zły”
7

TL; DR

Pisząc tę ​​odpowiedź, wciąż znajdowałem nowe alternatywy, więc po prostu napisałem trochę szczegółów na temat każdej z nich i zrobiłem statystyki. Zasadniczo możesz:

  • Przeczytaj odpowiedź Gillesa, która zapewnia czysty i szybki sposób na zrobienie tego (polega na /proc).
  • Skorzystaj z zasobów dokumentacji.
  • Użyj plików nagłówka C swojego systemu.
  • Użyj samego kodu źródłowego jądra.
  • Skorzystaj z /syskatalogu.

Po wykonaniu matematyki polecam (wśród moich alternatyw) korzystanie z /syssystemu plików, ponieważ wydaje się, że daje najlepszy wynik pod względem liczby wywołań systemowych. Możesz przejść bezpośrednio do tej sekcji, jeśli nie chcesz czytać o innych sztuczkach.

Korzystanie z zasobów dokumentacji

Chociaż możesz przegapić niektóre z nich, możesz użyć aproposdo wyświetlenia wszystkich stron podręcznika należących do sekcji 2 (wywołania systemowe):

$ apropos -s2 . | awk '{print $1}' | column

Usuń, columnjeśli nie chcesz fantazyjnych wyników skolumnizowanych.

Właśnie się o tym dowiedziałem, ale jest strona podręcznika systemowego Linuksa na temat wywołań systemowych, w której można znaleźć większość z nich.

$ man syscalls

Natknąłem się również na te dwie strony, które mogą być interesujące:

Korzystanie z plików nagłówków

Edycja: Teraz, jeśli chodzi o programowe (lub przynajmniej bez polegania na udokumentowanych funkcjach) określanie dostępnych wywołań systemowych, obawiam się, że jądro nie przechowuje tabeli swoich wywołań systemowych, przynajmniej nie w formie lista ciągów znaków (jak zapewne można się nimi posługiwać). Na tym poziomie mówimy raczej o adresach funkcji i wskaźnikach, niż o nazwach funkcji.

Właśnie przejrzałem mój /usr/includekatalog i grep-ed kilka rzeczy: możesz zainteresować następujące katalogi. Niektóre z nich mogą różnić się na twoim komputerze, w zależności od architektury i dystrybucji, ale jestem pewien, że będziesz w stanie je dostosować.

  • / usr / include / linux
  • / usr / include / x86_64-linux-gnu
  • / usr / include / sys
  • / usr / include / asm-generic

Szukając definicji funkcji w tym pliku, natrafisz na wiele wywołań systemowych, nawet jeśli nie zostaną one w pełni zdefiniowane. Uruchomiłem kilka grepsekund w tych katalogach i udało mi się znaleźć wzmianki o niektórych wywołaniach systemowych. Oto przykład:

$ grep 'sys_exit' /usr/include -R
asm-generic/unistd.h:__SYSCALL(__NR_exit, sys_exit)

Domyślam się, że innym sposobem na znalezienie niektórych z nich byłoby:

$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')'

Używanie kodu źródłowego jądra i jego tabeli syscall

Innym rozwiązaniem jest użycie samego kodu źródłowego jądra (a nie tylko nagłówków!) I znalezienie sposobu na jego efektywne przeszukiwanie. Ponieważ jądro zatwierdza 303395ac3bf3e2cb488435537d416bc840438fcb , może to być nieco łatwiejsze niż wcześniej. Oto przykład dla 3.13 (który jest moim jądrem):

$ wget https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/syscalls/syscall_64.tbl?id=refs/tags/v3.13 -O syscall_64.tbl

Teraz, gdy masz już tabelę syscalls, po prostu ją przejrzyj:

$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl

Możesz znaleźć sposób, używając unamei arch, aby pobrać tblplik bezpośrednio z git.kernel.org , w oparciu o twoją wersję jądra i architekturę.

Korzystanie z /syssystemu plików

Odpowiedź Gillesa dała mi trochę inspiracji i możesz znaleźć te wywołania systemowe w środku /sys/kernel/debug/tracing/events/syscalls. Ten katalog służy do monitorowania użycia każdego wywołania systemowego w systemie. Każde połączenie systemowe ma dwa katalogi:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

Dlatego, korzystając ls, grepi cut...

$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3

Statystyki

W moim systemie:

  • Korzystanie ze stron podręcznika ujawniło 440 wywołań systemowych.
  • grep-ing do __SYSCALLw plikach nagłówkowych ujawniła 212 wywołań systemowych.
  • Czytanie tabeli syscalls ze źródeł jądra ujawniło 346 wywołań systemowych.
  • Korzystanie z /sysujawnionych 290 wywołań systemowych.

Teraz, jeśli połączę wszystko razem ...

$ apropos -s2 . | awk '{print $1}' > system_calls.txt
$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')' >> system_calls.txt
$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl >> system_calls.txt
$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3 >> system_calls.txt

$ sort < system_calls.txt | uniq | wc -l
707

Proszę bardzo, 707 połączeń systemowych! Oczywiście liczba ta odzwierciedla bardzo elastyczną definicję „wywołania systemowego”, ponieważ 3.13 ma zapewniać tylko 274 wywołań systemowych (odczyt /syswydaje się być najbliższym rozwiązaniem).

John WH Smith
źródło
Szukam czegoś więcej w zakresie „odczytywania” systemowej tabeli wywołań w jakiś sposób, zamiast dowiedzieć się, które z wywołań systemowych są udokumentowane na stronach
podręcznika
Nie sądzę, aby jądro zachowało listę swoich wywołań systemowych, a przynajmniej nie jako listę ciągów. Zredagowałem swoją odpowiedź. Jeśli istnieje sposób, aby to zrobić, pozwolę, aby ktoś z większym doświadczeniem ode mnie odpowiedział;)
John WH Smith,
zastanawiałem się nad tym po dodaniu wywołania systemowego do jądra, a próba użycia go dała „funkcję niezaimplementowaną” i zastanawiałem się, czy istnieje jakiś sposób na uzyskanie tabeli syscall dla bieżącego jądra. kiedy wykonuję „#make install”, aktualizuję GRUB i uruchamiam nowe jądro, na jakim etapie nowe jądro otrzymuje odpowiednie pliki zawierające nowe wywołanie systemowe?
Swair
1
Jeśli połączenie systemowe nie zostanie znalezione, oznacza to, że nie zostało ono poprawnie wdrożone. Moja odpowiedź mówi, jak znaleźć wywołania systemowe Linuksa, ale nie jak debugować własne (ponieważ nie o to prosisz). Jeśli masz problemy z jego rozwinięciem, powinieneś zadać pytanie na ten temat i uniknąć problemu XY .
John WH Smith
@swair Bardzo rzadko jest dodawanie funkcji poprzez dodanie wywołania systemowego. Nie możemy z całą pewnością stwierdzić, co jest nie tak, ponieważ nie dostarczyłeś żadnego kodu (a jeśli twoje pytanie wymaga kodu C, tutaj jest nie na temat, ale w domu na stosie przepełnienia ). Podejrzewam, że zaimplementowałeś wywołanie systemowe (poprawnie lub nie) i próbujesz użyć go z programu w C, a także że brakuje Ci kroku pisania funkcji C, która wywołuje to wywołanie. Wywołanie systemowe nie jest zwykłym wywołaniem funkcji.
Gilles „SO- przestań być zły”
1

Wszystkie odpowiedzi są w porządku.

Jeśli szukasz konkretnej nazwy wywołania systemowego:

$ cat /proc/kallsyms | grep <sys_call_name>

Jeśli szukasz listy wszystkich wywołań systemowych:

$ cat /proc/kallsyms
Hamed Kamrava
źródło