Ajout d'un nouvel appel système à Linux 3.2.x avec un module de noyau chargeable [fermé]

11

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?

abhi
la source
Cette question est hors sujet ici: Unix et Linux concerne l'utilisation et l'administration, pas la programmation. Vous devriez demander sur Stack Overflow . Ne soyez pas si vague: créez un lien vers les publications que vous avez trouvées sur Stack Overflow et expliquez ce que vous avez trouvé non concluant ou contradictoire.
Gilles 'SO- arrête d'être méchant'
2
Je crois que cette question est beaucoup plus liée à Linux en tant qu'OS qu'à la programmation elle-même. Il est également très important de savoir quelles sont les possibilités d'extension de nos capacités système et quelles sont ses limites. Ceci, par exemple, vous fait comprendre pourquoi certaines fonctionnalités ne sont pas possibles à implémenter en tant que module chargeable et nécessitent des correctifs du noyau. Savoir pourquoi c'est ainsi peut aussi vous donner quelques idées sur la sécurité et la convivialité que les développeurs de noyau doivent faire. Est-ce que cette question serait plus sur le sujet si OP ne demandait que si c'était possible et pourquoi pas et comment mettre en œuvre cela?
Krzysztof Adamski
1
Il y a eu de nombreuses <stroke> flammes </stroke> discussions sur la liste de diffusion du noyau Linux, par exemple reiserfs a utilisé ses propres appels système, qui n'étaient pas vraiment appréciés par certains développeurs principaux, y compris Linus. Dans votre cas, j'utiliserais simplement 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.
peterh

Réponses:

14

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.cfichier, où sys_call_tableest défini. Sa taille est exactement __NR_syscall_max+1. __NR_syscall_maxest défini en arch/x86/kernel/asm-offsets_64.ctant que sizeof(syscalls) - 1(c'est le numéro du dernier appel système), où se syscalltrouve une table avec tous les appels système.

Une solution possible est de réutiliser un sys_setaltrootnumé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_tablevers 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_tablesymbole 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.

Krzysztof Adamski
la source
1

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.

PaulDaviesC
la source