J'espérais que quelqu'un pourrait expliquer les nuances de la macro __user utilisée dans la source du noyau Linux.
Tout d'abord, la macro:
# define __user __attribute__((noderef, address_space(1)))
Maintenant, après quelques recherches sur Google, j'ai lu que cette macro permet de désigner un pointeur comme appartenant à l'espace d'adressage de l'utilisateur et qu'il ne doit pas être déréférencé.
Je manque peut-être des faits évidents, mais quelqu'un pourrait-il expliquer les implications d'une telle macro? Par exemple, quel est un bon exemple de l'utilisation de cette macro? Encore une fois, pardonnez-moi si je manque quelque chose d'évident.
Pour mettre cela dans un certain contexte, je suis tombé sur la macro tout en examinant du code USB (linux/usbdevice_fs.h). Je recherche uniquement une compréhension générale de cette utilisation des macros (ou d'autres similaires) dans le noyau.
Merci d'avoir regardé!
Il permet à des outils comme épars d'indiquer aux développeurs du noyau qu'ils utilisent peut-être incorrectement un pointeur non fiable (ou un pointeur qui peut être invalide dans le mappage d'adresse virtuelle actuel).
Je pense que __user marque les pointeurs de l'espace utilisateur et dit au développeur/système de ne pas lui faire confiance. Si l'utilisateur vous donne un pointeur "invalide", le noyau essaie de le référencer (notez que le noyau peut référencer partout) et il peut corrompre son propre espace.
Par exemple, dans "lecture" (en vous usbdevice_fs.h), vous devriez vous fournir un tampon (__user) pour écrire le résultat. Vous devez donc utiliser copy_to_user, mais pas memcopy, strcpy ou quelque chose comme ça.
Remarque: Ce n'est pas une définition/description formelle, mais la seule partie que je connaisse.
Le __user
macro est définie avec d'autres macros comme __force
/__kernel
etc dans le fichier d'en-tête compiler.h. Ils ne sont en fait d'aucune utilité pour les compilateurs traditionnels, y compris GCC/ICC, etc. Mais ils sont utiles pour les outils d'analyse statique du noyau comme clairsemés (plus d'informations ici: Sparse - Linux Kernel Newbies). Lorsque vous mentionnez les macros comme __user
/__kernel
/__force
etc, il conserve une signification spéciale pour clairsemé. Dans la liste de diffusion du noyau Linux, Linus Torvalds explique son utilisation comme ceci:
Ceci est important à retenir: pour gcc, les annotations clairsemées n'ont pas de sens. Ils peuvent toujours être utiles juste pour dire au programmeur que "hé, ce pointeur que vous avez obtenu n'était pas un pointeur normal" d'une manière assez lisible, mais au final, à moins que vous n'utilisiez pas vraiment faire quoi que ce soit.
TOUTEFOIS. Lorsque vous faites utilisez l'analyse, c'est une tout autre affaire. Pour "clairsemé", ce "__iomem" a beaucoup de sens:
# define __iomem __attribute__((noderef, address_space(2)))
c.-à-d. "iomem" signifie deux choses distinctes: cela signifie que peu de gens devraient se plaindre
si le pointeur est jamais déréférencé (c'est un pointeur "noderef") directement, et qu'il est dans "l'espace d'adressage 2" par opposition à l'espace d'adressage normal (0).
Maintenant, cela signifie que clairsemé se plaindra si un tel pointeur est jamais passé dans une fonction qui veut un pointeur régulier (parce que c'est pas un pointeur normal, et vous ne devriez évidemment pas ne faites pas des choses comme "strcmp ()", etc.), et clairsemé se plaindra également si vous essayez de le convertir en un autre pointeur dans un autre espace d'adressage.