web-dev-qa-db-fra.com

Que sont vdso et vsyscall?

J'ai fait Sudo cat /proc/1/maps -vv

J'essaie de donner un sens à la sortie. Je peux voir beaucoup de bibliothèques partagées être mappées sur le segment de mappage de mémoire comme prévu.

7f3c00137000-7f3c00179000 r-xp 00000000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00179000-7f3c00379000 ---p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00379000-7f3c0037a000 r--p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037a000-7f3c0037b000 rw-p 00043000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037b000-7f3c00383000 r-xp 00000000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00383000-7f3c00583000 ---p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00583000-7f3c00584000 r--p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00584000-7f3c00585000 rw-p 00009000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00585000-7f3c0059b000 r-xp 00000000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0059b000-7f3c0079b000 ---p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0079b000-7f3c0079c000 r--p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0

Vers la fin, il y a quelque chose comme

7f3c0165b000-7f3c0177e000 rw-p 00000000 00:00 0                          [heap]
7fff97863000-7fff97884000 rw-p 00000000 00:00 0                          [stack]
7fff97945000-7fff97946000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Que signifient vdso et vsyscall? vsyscall est-elle la partie noyau de la mémoire? Ce serait formidable si quelqu'un pouvait éclairer la question.

76
liv2hak

Les segments vsyscall et vDSO sont deux mécanismes utilisés pour accélérer certains appels système sous Linux. Par exemple, gettimeofday est généralement invoqué via ce mécanisme. Le premier mécanisme introduit a été vsyscall , qui a été ajouté comme moyen d'exécuter des appels système spécifiques qui n'ont besoin d'aucun niveau de privilège réel pour s'exécuter afin de réduire la surcharge des appels système. Suivant l'exemple précédent, tout ce que gettimeofday doit faire est de lire l'heure actuelle du noyau. Il existe des applications qui appellent gettimeofday fréquemment (par exemple pour générer des horodatages), au point qu'elles se soucient même d'un peu de surcharge. Pour résoudre ce problème, le noyau mappe dans l'espace utilisateur une page contenant l'heure actuelle et une implémentation rapide de gettimeofday (c'est-à-dire juste une fonction qui lit le temps enregistré dans vsyscall ). En utilisant cet appel système virtuel, la bibliothèque C peut fournir un gettimeofday rapide qui n'a pas la surcharge introduite par le changement de contexte entre l'espace du noyau et l'espace utilisateur généralement introduit par le modèle classique d'appel système INT 0x80 ou SYSCALL.

Cependant, ce mécanisme vsyscall a certaines limites: la mémoire allouée est petite et ne permet que 4 appels système, et, plus important et sérieux, le La page vsyscall est allouée statiquement à la même adresse dans chaque processus, car l'emplacement du vsyscall la page est clouée dans le noyau ABI. Cette allocation statique de vsyscall compromet l'avantage introduit par la randomisation de l'espace mémoire couramment utilisée par Linux. Un attaquant, après avoir compromis une application en exploitant un débordement de pile, peut invoquer un appel système à partir de la page vsyscall avec des paramètres arbitraires. Tout ce dont il a besoin est l'adresse de l'appel système, qui est facilement prévisible car elle est allouée statiquement (si vous essayez de relancer votre commande même avec différentes applications, vous remarquerez que l'adresse du vsyscall ne change pas). Ce serait bien de supprimer ou au moins de randomiser l'emplacement de la page vsyscall pour contrecarrer ce type d'attaque. Malheureusement, les applications dépendent de l'existence et de l'adresse exacte de cette page, donc rien ne peut être fait.

Ce problème de sécurité a été résolu en remplaçant toutes les instructions d'appel système à des adresses fixes par une instruction d'interruption spéciale. Une application essayant d'appeler dans la page vsyscall interceptera le noyau, qui émulera ensuite l'appel système virtuel souhaité dans l'espace noyau. Le résultat est un appel système noyau émulant un appel système virtuel qui a été placé là pour éviter l'appel système noyau en premier lieu. Le résultat est un vsyscall qui prend plus de temps à exécuter mais, surtout, ne casse pas l'ABI existant. Dans tous les cas, le ralentissement ne sera visible que si l'application essaie d'utiliser la page vsyscall au lieu de la vDSO .

Le vDSO offre les mêmes fonctionnalités que le vsyscall, tout en surmontant ses limites. Le vDSO (Virtual Dynamically Linked Shared Objects) est une zone de mémoire allouée dans l'espace utilisateur qui expose certaines fonctionnalités du noyau dans l'espace utilisateur de manière sûre. Cela a été introduit pour résoudre les menaces de sécurité causées par le vsyscall. Le vDSO est alloué dynamiquement, ce qui résout les problèmes de sécurité et peut avoir plus de 4 appels système. Les liens vDSO sont fournis via la bibliothèque glibc. L'éditeur de liens établira un lien dans la fonctionnalité glibc vDSO , à condition qu'une telle routine ait un accompagnement vDSO version, comme gettimeofday. Lorsque votre programme s'exécute, si votre noyau ne prend pas en charge vDSO , un appel système traditionnel sera effectué.

Crédits et liens utiles:

133
Giuseppe Pes

Je veux juste ajouter que maintenant dans les nouveaux noyaux, vDSO n'est pas utilisé uniquement pour les appels système "sûrs" mais il est utilisé pour décider quel mécanisme d'appel système est la méthode préférée pour appeler un appel système sur le système.

7
incompetent