Systemaufrufe werden beim Ausführen des Kernels unterstützt

9

Gibt es eine Möglichkeit, die Anzahl oder Liste der Systemaufrufe abzurufen, die vom derzeit ausgeführten Linux-Kernel unterstützt werden? Ich möchte also einen Weg finden, die Syscall-Tabelle eines laufenden Kernels zu "lesen".

Swair
quelle

Antworten:

15

Die Datei /proc/kallsymslistet alle Symbole des laufenden Kernels auf. Konventionell haben Systemaufrufe einen Namen, der mit beginnt sys_. Auf einem 64-Bit-System haben Systemaufrufe für 32-Bit-Programme einen Namen, der mit beginnt sys32_. Genau genommen listet dies interne Kernelfunktionen auf, nicht Systemaufrufe, aber ich denke, dass die Korrespondenz funktioniert (jeder Systemaufruf ruft eine interne Kernelfunktion auf, um die Aufgabe zu erledigen, und ich denke, der Name ist immer der Name des Systemaufrufs mit sys_vorangestelltem Namen ).

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

Dies sind normalerweise keine nützlichen Informationen, da sich Systemaufrufe sehr langsam ändern. Optionale Komponenten bieten Funktionen in Bezug auf vorhandene Systemaufrufe, wobei allgemeine Funktionen wie Geräte (mit ioctl, wenn readund writeschneidet es nicht), Dateisysteme, Sockets usw. verwendet werden. Wenn Sie die Liste der unterstützten Systemaufrufe ermitteln, erhalten Sie keine Informationen zu den Funktionen dass das System unterstützt. Andere interne Funktionsnamen helfen ebenfalls nicht, da sich diese sehr schnell ändern: Der Name der Funktion, die eine Funktion in einer Kernelversion implementiert, kann sich in der nächsten Version ändern.

Gilles 'SO - hör auf böse zu sein'
quelle
+1. Das habe ich gemeint, als ich sagte "Ich lasse jemanden mit mehr Erfahrung als ich dir antworten" . Da /proc/kallsymses wie jede andere Datei bearbeitet werden kann, ist es außerdem recht einfach, es in einem Programm zu verwenden.
John WH Smith
2
@JohnWHSmith „Kann wie jede andere Datei bearbeitet werden“… mit der Einschränkung, dass diese Datei auf Systemen mit Kernel-ASLR nur von root gelesen werden sollte.
Gilles 'SO - hör auf böse zu sein'
7

TL; DR

Ich habe beim Schreiben dieser Antwort immer wieder neue Alternativen gefunden, also habe ich nur ein paar Details zu jeder dieser Antworten geschrieben und einige Statistiken erstellt. Grundsätzlich können Sie entweder:

  • Lesen Sie die Antwort von Gilles, die eine saubere und schnelle Möglichkeit bietet (abhängig von /proc).
  • Verwenden Sie die Dokumentationsressourcen.
  • Verwenden Sie die C-Header-Dateien Ihres Systems.
  • Verwenden Sie den Kernel-Quellcode selbst.
  • Verwenden Sie das /sysVerzeichnis.

Nach dem Rechnen würde ich (unter meinen Alternativen) die Verwendung des /sysDateisystems empfehlen , da es hinsichtlich der Anzahl der Systemaufrufe das beste Ergebnis zu liefern scheint. Sie können direkt zu diesem Abschnitt springen, wenn Sie nicht über die anderen Tricks lesen möchten.

Verwenden der Dokumentationsressourcen

Während Sie möglicherweise einige davon verpassen, können Sie damit aproposalle zu Abschnitt 2 gehörenden Manpages (Systemaufrufe) auflisten:

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

Entfernen columnSie diese Option, wenn Sie keine ausgefallene kolumnisierte Ausgabe wünschen.

Ich habe es gerade herausgefunden, aber es gibt eine Linux-Manpage über Systemaufrufe, und Sie werden die meisten darin finden können.

$ man syscalls

Ich bin auch auf diese beiden Websites gestoßen, die interessant sein könnten:

Header-Dateien verwenden

Bearbeiten: Wenn es darum geht, programmgesteuert (oder zumindest ohne sich auf dokumentierte Funktionen zu verlassen) zu bestimmen, welche Systemaufrufe verfügbar sind, führt der Kernel leider keine Tabelle seiner Systemaufrufe, zumindest nicht in Form von eine Liste von Zeichenfolgen (wie Sie wahrscheinlich erwarten würden, sie zu manipulieren). Auf dieser Ebene geht es eher um Funktionsadressen und -zeiger als um Funktionsnamen.

Ich habe gerade mein /usr/includeVerzeichnis durchsucht und grepein paar Dinge durchgesehen: Vielleicht finden Sie die folgenden Verzeichnisse interessant. Einige davon können je nach Architektur und Distribution auf Ihrem Computer unterschiedlich sein, aber ich bin sicher, dass Sie sie anpassen können.

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

Wenn Sie in dieser Datei nach Funktionsdefinitionen suchen, werden Sie auf viele Systemaufrufe stoßen, die dort jedoch nicht vollständig definiert sind. Ich habe einige grepSekunden in diesen Verzeichnissen ausgeführt und konnte einige Systemaufrufe erwähnen. Hier ist ein Beispiel:

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

Ich vermute also, dass ein anderer Weg, einige von ihnen zu finden, wäre:

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

Verwenden des Quellcodes des Kernels und seiner Syscall-Tabelle

Eine andere Lösung besteht darin, den Kernel-Quellcode selbst (und nicht nur die Header!) Zu verwenden und einen Weg zu finden, ihn effizient zu durchsuchen. Da das Kernel 303395ac3bf3e2cb488435537d416bc840438fcb festschreibt , ist dies möglicherweise etwas einfacher als zuvor. Hier ist ein Beispiel für 3.13 (das ist mein Kernel):

$ 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

Nachdem Sie die eigentliche Syscalls-Tabelle erhalten haben, durchsuchen Sie sie einfach:

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

Sie könnten einen Weg finden, die Datei mit unameund direkt von git.kernel.org herunterzuladenarchtbl , basierend auf Ihrer laufenden Kernelversion und .

Verwendung der /sys Dateisystems

Gilles 'Antwort hat mich ein wenig inspiriert, und vielleicht finden Sie diese Systemaufrufe darin /sys/kernel/debug/tracing/events/syscalls. Dieses Verzeichnis wird verwendet, um die Verwendung jedes Systemaufrufs auf dem System zu überwachen. Jeder Systemaufruf enthält zwei Verzeichnisse:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

Daher ist die Verwendung ls, grepund cut...

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

Statistiken

Auf meinem System:

  • Die Verwendung der Manpages ergab 440 Systemaufrufe.
  • grep-ing für __SYSCALLin den Header-Dateien wurden 212 Systemaufrufe angezeigt.
  • Das Lesen der Syscalls-Tabelle aus den Kernelquellen ergab 346 Systemaufrufe.
  • Verwenden von /sysoffenbarten 290 Systemaufrufen.

Nun, wenn ich alles zusammenbringe ...

$ 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

Los geht's, 707 Systemaufrufe! Natürlich spiegelt diese Nummer eine sehr flexible Definition eines "Systemaufrufs" wider, da 3.13 nur 274 Systemaufrufe liefern soll (Lesen /sysscheint die naheliegendste Lösung zu sein).

John WH Smith
quelle
Ich suche nach einer Möglichkeit, die Systemaufruftabelle auf irgendeine Weise zu "lesen", anstatt herauszufinden, welche der Systemaufrufe in Manpages dokumentiert sind
Swair,
Ich glaube nicht, dass der Kernel eine Liste seiner Systemaufrufe führt, zumindest nicht als Liste von Zeichenfolgen. Ich habe meine Antwort bearbeitet. Wenn es einen tatsächlichen Weg gibt, werde ich jemanden mit mehr Erfahrung als ich antworten lassen;)
John WH Smith
Ich habe mich darüber gewundert, nachdem ich dem Kernel einen Systemaufruf hinzugefügt hatte und versucht habe, ihn zu verwenden, was "Funktion nicht implementiert" ergab, und ich habe mich gefragt, ob es eine Möglichkeit gibt, die Syscall-Tabelle für den aktuellen Kernel abzurufen. Wenn ich '#make install' mache, grub aktualisiere und einen neuen Kernel starte, in welchem ​​Schritt erhält der neue Kernel relevante Include-Dateien, die den neuen Systemaufruf enthalten?
Swair
1
Wenn Ihr Systemaufruf nicht gefunden wurde, haben Sie ihn nicht korrekt implementiert. Meine Antwort zeigt Ihnen, wie Sie die Systemaufrufe von Linux finden, aber nicht, wie Sie Ihre eigenen debuggen (da dies nicht das ist, wonach Sie fragen). Wenn Sie Probleme bei der Entwicklung haben, sollten Sie eine spezielle Frage dazu stellen und das XY-Problem vermeiden .
John WH Smith
@swair Es ist sehr ungewöhnlich, Funktionen durch Hinzufügen eines Systemaufrufs hinzuzufügen. Wir können nicht sicher sagen, was falsch ist, da Sie keinen Code angegeben haben (und wenn Ihre Frage C-Code erfordert, ist dies hier nicht zum Thema, aber zu Hause bei Stack Overflow ). Ich vermute, dass Sie einen Systemaufruf implementiert haben (richtig oder nicht) und dass Sie versuchen, ihn aus einem C-Programm heraus zu verwenden, und dass Sie den Schritt des Schreibens einer C-Funktion verpassen, die den Systemaufruf ausführt. Ein Systemaufruf ist kein gewöhnlicher Funktionsaufruf.
Gilles 'SO - hör auf böse zu sein'
1

Alle Antworten sind in Ordnung.

Wenn Sie nach einem bestimmten Systemaufrufnamen suchen:

$ cat /proc/kallsyms | grep <sys_call_name>

Wenn Sie nach einer Liste aller Systemaufrufe suchen:

$ cat /proc/kallsyms
Hamed Kamrava
quelle