Hinzufügen eines neuen Systemaufrufs zu Linux 3.2.x mit einem ladbaren Kernelmodul [geschlossen]

11

Ich möchte einen bestimmten neuen Systemaufruf im Linux-Kernel 3.2.x hinzufügen, aber als ladbares Kernelmodul (da ich den Kernel nicht immer wieder neu kompilieren möchte).

Ich habe viele Beiträge im Internet und auch auf SO gelesen, und einige Orte behaupten, dass die Implementierung von Systemaufrufen als ladbare Module nicht möglich ist, während andere sagen, dass dies möglich ist.

Welches ist es? Wie wird es gemacht, wenn es möglich ist?

abhi
quelle
Diese Frage ist hier nicht zum Thema: Bei Unix und Linux geht es um Nutzung und Administration, nicht um Programmierung. Sie sollten nach Stapelüberlauf fragen . Seien Sie nicht so vage: Verlinken Sie auf die Beiträge, die Sie bei Stack Overflow gefunden haben , und erklären Sie, was Sie als nicht schlüssig oder widersprüchlich empfunden haben.
Gilles 'SO - hör auf böse zu sein'
2
Ich glaube, dass diese Frage viel mehr mit Linux als Betriebssystem zu tun hat als mit der Programmierung selbst. Es ist auch sehr wichtig zu wissen, welche Möglichkeiten es gibt, unsere Systemfähigkeiten zu erweitern, und wo ihre Grenzen liegen. Auf diese Weise verstehen Sie beispielsweise, warum einige Funktionen nicht als ladbares Modul implementiert werden können und Kernel-Patches erforderlich sind. Wenn Sie wissen, warum dies so ist, erhalten Sie möglicherweise auch einige Ideen zu Sicherheit und Benutzerfreundlichkeit, die Kernel-Entwickler entwickeln müssen. Wäre diese Frage eher thematisch, wenn OP nur fragen würde, ob dies möglich ist und warum nicht und nicht, wie dies umgesetzt werden soll?
Krzysztof Adamski
1
Es gab zahlreiche <stroke> Flames </ Stroke> -Diskussionen auf der Linux-Kernel-Mailingliste, zum Beispiel verwendeten reiserfs eigene Syscalls, die von einigen Kernentwicklern, einschließlich Linus, nicht wirklich geliebt wurden. In Ihrem Fall würde ich einfach ioctl()s für die Aufgabe verwenden, sie sind leicht modularisierbar. Afaik ist der Hauptgrund dafür, dass dies so schwierig wie möglich ist, dass die Anzahl der Systemaufrufe sehr hartcodiert ist und niemand das Chaos will, was es ins Bild bringen würde. Es gibt jedoch zahlreiche Kernel-Schnittstellen, um dieselbe Funktionalität zu erreichen, z. B. sysfs, ioctls oder dergleichen.
Peterh - Wiedereinsetzung Monica

Antworten:

14

Dies ist nicht möglich, da die Systemaufruftabelle (aufgerufen sys_call_table) ein Array mit statischer Größe ist. Die Größe wird beim Kompilieren durch die Anzahl der registrierten Systemaufrufe bestimmt. Dies bedeutet, dass kein Platz für einen anderen vorhanden ist.

Sie können die Implementierung beispielsweise für die x86-Architektur in der arch/x86/kernel/syscall_64.cDatei überprüfen , in der sie sys_call_tabledefiniert ist. Seine Größe ist genau __NR_syscall_max+1. __NR_syscall_maxist definiert arch/x86/kernel/asm-offsets_64.cals sizeof(syscalls) - 1(es ist die Anzahl der letzten Systemaufrufe), wobei syscalleine Tabelle mit allen Systemaufrufen ist.

Eine mögliche Lösung besteht darin, eine vorhandene (oder veraltete, wenn Ihre Architektur eine hat, siehe sys_setaltrootzum Beispiel) Syscall-Nummer mit Ihrer wiederzuverwenden, da dies nicht mehr Speicherplatz erfordert. Einige Architekturen haben möglicherweise auch Lücken in der Syscall-Tabelle (wie die 64-Bit-Version von x86), sodass Sie diese auch verwenden können.

Sie können diese Technik verwenden, wenn Sie einen neuen Systemaufruf entwickeln und nur einen Neustart während des Experimentierens vermeiden möchten. Sie müssen Ihren neuen Systemaufruf definieren, den vorhandenen Eintrag in der Syscall-Tabelle suchen und ihn dann von Ihrem Modul ersetzen.

Dies vom Kernelmodul aus zu tun ist nicht trivial, da der Kernel ab sys_call_tableVersion 2.6 nicht in Module exportiert wird (die letzte Kernelversion, in die dieses Symbol exportiert wurde, war 2.5.41).

Eine Möglichkeit, dies zu umgehen, besteht darin, den Kernel so zu ändern, dass das sys_call_tableSymbol in Module exportiert wird . Dazu müssen Sie die folgenden zwei Zeilen hinzufügen kernel/kallsyms.c( tun Sie dies nicht auf Produktionsmaschinen ):

extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);

Eine andere Technik besteht darin, die Syscall-Tabelle dynamisch zu finden. Sie iterieren über den Kernelspeicher und vergleichen jedes Wort mit einem Zeiger auf eine bekannte Systemaufruffunktion. Da Sie den Offset dieses bekannten Systemaufrufs in der Tabelle kennen, können Sie die Anfangsadresse der Tabelle berechnen.

Krzysztof Adamski
quelle
1

Leider können Sie dem Kernel keine Systemaufrufe als ladbare Module hinzufügen. Sie müssen sich die Mühe machen, den Kernel jedes Mal zu kompilieren, wenn Sie einen neuen Systemaufruf hinzufügen.

PaulDaviesC
quelle