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 en arch/x86/kernel/asm-offsets_64.c
tant que sizeof(syscalls) - 1
(c'est le numéro du dernier appel système), où se syscall
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'était 2.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 ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
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.