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?
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.Antworten:
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.c
Datei überprüfen , in der siesys_call_table
definiert ist. Seine Größe ist genau__NR_syscall_max+1
.__NR_syscall_max
ist definiertarch/x86/kernel/asm-offsets_64.c
alssizeof(syscalls) - 1
(es ist die Anzahl der letzten Systemaufrufe), wobeisyscall
eine Tabelle mit allen Systemaufrufen ist.Eine mögliche Lösung besteht darin, eine vorhandene (oder veraltete, wenn Ihre Architektur eine hat, siehe
sys_setaltroot
zum 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_table
Version 2.6 nicht in Module exportiert wird (die letzte Kernelversion, in die dieses Symbol exportiert wurde, war2.5.41
).Eine Möglichkeit, dies zu umgehen, besteht darin, den Kernel so zu ändern, dass das
sys_call_table
Symbol in Module exportiert wird . Dazu müssen Sie die folgenden zwei Zeilen hinzufügenkernel/kallsyms.c
( tun Sie dies nicht auf Produktionsmaschinen ):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.
quelle
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.
quelle