Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[ NETBSD ]KLM et appels systemes

2 réponses
Avatar
moi
Bonjour.

D'après ce que j'ai lu, il serait possible de remplacer les appels
systèmes natifs NetBSD par se propres implémentations. Ai-je bien
compris ce que j'ai lu?

J'ai vu aussi un exemple dans les sources du noyau mais je n'arrive pas
trop a le comprendre (peut-être la fatigue en fin de journée). le
"readme" indique:

4.0 System call modules

System calls as loadable modules use one of two approaches.

If the system call slot is unspecified (-1), it will attempt
to locate (and allocate) the next free call slot that points
to the address of the "lkmnosys" function (an alias for the
"nosys" function). It replaces this with the user's call;
the user can tell which slot was allocated using the "modstat"
command (the call slot is indicated by the value of "Off").

If the system call slot is specified, it will replace that
specific call (assuming it is in range of the entries in the
sysent[] table). Care should be taken when replacing system
calls. Good candiates are calls which the user is attempting
to repair or make POSIX compliant. It is possible to replace
all calls, although care should be taken with the "ioctl()"
call, as it is the interface for the lkm loader.

Ca veut dire quoi tout ça?

L'exemple trouvé dans les sources ci-dessous: (je passe les #include du
début)

Dans les 3 lignes ci-dessous, pourquoi le __P ? A quoi servent-elles?


> int example_syscall __P((struct lwp *, void *, register_t *));
> int syscall_example_lkmentry __P((struct lkm_table *, int, int));

> static int syscall_load __P((struct lkm_table *, int));


Si j'ai bien compris les lignes ci-dessous servent à définir une
nouvelle entrée dans la table des appels systèmes, et la macro
MOD_SYSCALL contient ce qu'il faut pour initialiser la bonne structure.

> /*
> * These two entries define our system call and module information. We
> * have 0 arguments to our system call.
> */
> static struct sysent newent = {
> /* # of args, args size, MP-safe, fn. pointer */
> 0, 0, 0, example_syscall
> };

> MOD_SYSCALL( "syscall_example", -1, &newent)

Les lignes ci-dessous sont claires .....
> /*
> * This function is called each time the module is loaded. Technically,
> * we could have made this "lkm_nofunc" in the "DISPATCH" in
> * "syscall_example_lkmentry()",
> * but it's a convenient place to kick a copyright out to the console.
> */
> static int
> syscall_load( lkmtp, cmd)
> struct lkm_table *lkmtp;
> int cmd;
> {
> /* print copyright on console*/
> printf("Sample Loaded system call\n");
> printf("Copyright (c) 1993 Terrence R. Lambert\n");
> printf("All rights reserved\n");

> return (0);
> }


A partir de la je ne suis plus ....

A quoi sert le DISPATCH?

/*
* External entry point; should generally match name of .o file +
'_lkmentry'.
* The arguments are always the same for all loaded modules. The "load",
* "unload", and "stat" functions in "DISPATCH" will be called under
* their respective circumstances. If no function is desired, lkm_nofunc()
* should be supplied. They are called with the same arguments (cmd is
* included to allow the use of a single function, ver is included for
* version matching between modules and the kernel loader for the modules).
*
* Since we expect to link in the kernel and add external symbols to
* the kernel symbol name space in a future version, generally all
* functions used in the implementation of a particular module should
* be static unless they are expected to be seen in other modules or
* to resolve unresolved symbols alread existing in the kernel (the
* second case is not likely to ever occur).
*
* The entry point should return 0 unless it is refusing load (in which
* case it should return an errno from errno.h).
*/
int
syscall_example_lkmentry(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp,cmd,ver,syscall_load,lkm_nofunc,lkm_nofunc)
}

Mon idée serait d'"intercepter" certains appels systèmes pour faire deux
ou trois actions avant d'appeler l'appel système d'origine. Est-ce
possible simplement? Est-ce que ça existe deja?

Si vous connaissez un lien ou un bouquin traitant du sujet je veux bien
les références.

Je vous remercie d'avance pour vos explications.

2 réponses

Avatar
Manuel Bouyer
moi wrote:
Bonjour.

D'après ce que j'ai lu, il serait possible de remplacer les appels
systèmes natifs NetBSD par se propres implémentations. Ai-je bien
compris ce que j'ai lu?

J'ai vu aussi un exemple dans les sources du noyau mais je n'arrive pas
trop a le comprendre (peut-être la fatigue en fin de journée). le
"readme" indique:

4.0 System call modules

System calls as loadable modules use one of two approaches.

If the system call slot is unspecified (-1), it will attempt
to locate (and allocate) the next free call slot that points
to the address of the "lkmnosys" function (an alias for the
"nosys" function). It replaces this with the user's call;
the user can tell which slot was allocated using the "modstat"
command (the call slot is indicated by the value of "Off").

If the system call slot is specified, it will replace that
specific call (assuming it is in range of the entries in the
sysent[] table). Care should be taken when replacing system
calls. Good candiates are calls which the user is attempting
to repair or make POSIX compliant. It is possible to replace
all calls, although care should be taken with the "ioctl()"
call, as it is the interface for the lkm loader.

Ca veut dire quoi tout ça?


Ben soit on donne -1 comme numero d'appel systeme et il se debrouille
pour en trouver un libre, soit on force un numero particulier, et
ca peut eventuellement servir a remplacer un appel systeme existant


L'exemple trouvé dans les sources ci-dessous: (je passe les #include du
début)

Dans les 3 lignes ci-dessous, pourquoi le __P ? A quoi servent-elles?


C'est pour compiler avec des compilos anciens qui ne comprennent pas
les prototype: on fait soit
#define P(a)
soit
#define P(a) a
en fonction du compilo

mais bon, c'est en cours de disparition, on est en train de supprimer
les __P() petit a petit


int example_syscall __P((struct lwp *, void *, register_t *));
int syscall_example_lkmentry __P((struct lkm_table *, int, int));

static int syscall_load __P((struct lkm_table *, int));




Si j'ai bien compris les lignes ci-dessous servent à définir une
nouvelle entrée dans la table des appels systèmes, et la macro
MOD_SYSCALL contient ce qu'il faut pour initialiser la bonne structure.

/*
* These two entries define our system call and module information. We
* have 0 arguments to our system call.
*/
static struct sysent newent = {
/* # of args, args size, MP-safe, fn. pointer */
0, 0, 0, example_syscall
};

MOD_SYSCALL( "syscall_example", -1, &newent)



Oui c'est ca


[...]



A partir de la je ne suis plus ....

A quoi sert le DISPATCH?


En fait, une seule fonction sert de point d'entree a l'appel systeme
pour les differentes operations: syscall_example_lkmentry().
A partir de cette fonction il faut apeller la bonne (load, unload, stat, ...)
en fonction de la commande. DISPATCH() est une macro qui met ca en
place (c'est un swich(){}, en gros).


Mon idée serait d'"intercepter" certains appels systèmes pour faire deux
ou trois actions avant d'appeler l'appel système d'origine. Est-ce
possible simplement?


Oui, il suffit de faire un LKM qui reprend le numero de l'appel systeme
en question, et apelle la fonction de l'appel systeme d'origine apres
avoir fait le traitement.

--
Manuel Bouyer
NetBSD: 26 ans d'experience feront toujours la difference
--


Avatar
moi
Manuel Bouyer wrote:

[ ...]

Oui, il suffit de faire un LKM qui reprend le numero de l'appel systeme
en question, et apelle la fonction de l'appel systeme d'origine apres
avoir fait le traitement.



Merci pour tous ces éclaircissements. Je vais étudier tout celà d'un peu
plus près et je reviendrai si j'ai des questions. Et puisque l'occasion
se présente, merci également pour le boulot effectué sur NetBSD/Xen.