Je veux ajouter un nouvel appel système particulier dans le noyau Linux 3.2.x mais en tant que module de noyau chargeable (car je ne veux pas recompiler le noyau encore et encore)
J'ai lu de nombreux articles sur Internet et également sur SO, et certains endroits affirment que l'implémentation d'appels système en tant que modules chargeables n'est pas possible, tandis que d'autres disent que c'est possible.
Lequel est-ce? Comment cela se fait-il si c'est possible?
ioctl()
s pour la tâche, ils sont facilement modulables. Afaik est la principale raison pour laquelle il est aussi difficile que possible de faire en sorte que le nombre d'appels système soit hautement codé en dur et que personne ne veuille le chaos ce qu'il obtiendrait dans l'image. Mais il existe de nombreuses interfaces du noyau pour atteindre les mêmes fonctionnalités, par exemple sysfs, ioctls ou autres.Réponses:
Ce n'est pas possible car la table d'appels système (appelée
sys_call_table
) est un tableau de taille statique. Et sa taille est déterminée au moment de la compilation par le nombre d'appels système enregistrés. Cela signifie qu'il n'y a pas de place pour un autre.Vous pouvez vérifier l'implémentation par exemple de l'architecture x86 dans le
arch/x86/kernel/syscall_64.c
fichier, oùsys_call_table
est défini. Sa taille est exactement__NR_syscall_max+1
.__NR_syscall_max
est défini enarch/x86/kernel/asm-offsets_64.c
tant quesizeof(syscalls) - 1
(c'est le numéro du dernier appel système), où sesyscall
trouve une table avec tous les appels système.Une solution possible est de réutiliser un
sys_setaltroot
numéro syscall existant (ou obsolète si votre architecture en a un, voir par exemple) avec le vôtre car cela ne nécessitera pas plus d'espace en mémoire. Certaines architectures peuvent également avoir des trous dans la table syscall (comme la version 64 bits de x86), vous pouvez donc également l'utiliser.Vous pouvez utiliser cette technique si vous développez un nouvel appel système et que vous souhaitez simplement éviter de redémarrer lors de l'expérimentation. Vous devrez définir votre nouvel appel système, rechercher une entrée existante dans la table syscall, puis la remplacer à partir de votre module.
Faire cela à partir du module du noyau n'est pas anodin car le noyau n'exporte pas
sys_call_table
vers les modules à partir de la version 2.6 (la dernière version du noyau qui avait ce symbole exporté l'était2.5.41
).Une façon de contourner ce problème est de changer votre noyau pour exporter le
sys_call_table
symbole vers les modules. Pour ce faire, vous devez ajouter les deux lignes suivantes àkernel/kallsyms.c
( ne faites pas cela sur les machines de production ):Une autre technique consiste à trouver dynamiquement la table syscall. Vous parcourez la mémoire du noyau en comparant chaque mot avec un pointeur à une fonction d'appel système connue. Puisque vous connaissez le décalage de ce syscall connu dans la table, vous pouvez calculer l'adresse de début de table.
la source
Malheureusement, vous ne pouvez pas ajouter d'appels système au noyau en tant que modules chargeables. Vous devez prendre la peine de compiler le noyau chaque fois que vous ajoutez un nouvel appel système.
la source