# Virtualisation
## Principe
Objectif : Faire fonctionner plusieurs systèmes d’exploitation sur une même machine physique (pour peu que ce soit sur une architecture équivalente)
Idée d'avoir des performances presque natives parce que peu ou pas d’émulation d’instructions
:::info
L'émulation est l'idée d'avoir des architectures différentes
:::
**Cas d’utilisation**
- Standardiser / Déployer des environnements (e.g. Docker)
- Faciliter la migration de systèmes
- Mutualiser / Distribuer des ressources physiques (e.g. Cloud)
## Rappels

**Machine virtuelle (VM)** : machine dont la couche matérielle a été virtualisée
**Hyperviseur (VMM : monitor)** : logiciel mettant en place la virtualisation
Nouvelle organisation en couches :
- Couche matérielle hôte : composants physiques réels
- Couche logicielle hôte : applications et l’OS de la machine de base
- Couches matérielles invitées (guest) : composants matériels virtualisés des machines virtuelles
- Couches logicielles invitées (guest) : applications et l’OS des machines virtuelles
- Couche logicielle de gestion des machines virtuelles : hyperviseur

- **Type 1 :** Server virtualization, bare metal
- Debug d’OS
- Permet d’intercepter toutes les interactions entre l’OS et le matériel
- Ex : ESXI, Xen, hyperV, ramooflax
- **Type 2 :** Hosted virtualization
- Tourne par-dessus un OS, l’hyperviseur est une application d’un OS hôte et fait tourner des OS invités
- Historiquement plus lent qu’un hyperviseur de type 1 (avant support matériel pour la virtualisation) car il devait se battre avec les autres processus de l’OS pour avoir des ressources et faire tourner un OS invité
- Exemples : VMware Workstation, VMware Fusion, VirtualBox
**Requirements de popek et Goldberg :**
- Equivalence/fidelity : pas de divergence comportementale entre virtualisé et non-virtualisé
- Resource control / Safety → Faire en sorte qu’une VM ne puisse pas écrire dans la mémoire d’une autre VM, etc. (contrôle des ressources par le VMM)
- Efficiency / Perf → Alors qu’un émulateur émule *tout*, un VMM doit se poser la question de ce qu’il doit émuler ou pas (et émuler le moins possible pour maximiser les performances) -> **minimum d'interventions**
Divisible en 3 niveaux:
- Virtualisation du CPU
- Virtualisation de la mémoire
- Virtualisation des périphériques
## Virtualisation du CPU
Problématique du partage du temps CPU et des instructions ring 0
On peut classer les instruction en 3 types :
- privilégié → le VMM doit intercepter l’instruction pour faire croire à la VM que la ressource est telle qu’elle le croit (ex : avec l’IDT)
- Sensible → ça touche à la configuration
- Controle → écriture (en général compris dans les privilégiées, existe pas vraiment en x86)
- comportement → lecture
- normal (le reste)
:::warning
Pour virtualiser il faut que
$\{sensibles\} \subset \{privilegiees\}$
:::
| Sensible | Privilégiée | Normal (à laisser passer) |
| --- | --- | --- |
| INT | IN | ADD |
| JMP FAR | OUT | SUB |
| CALL FAR | Tous les STORE | AND |
| Tous les LOAD | | POP |
| IRET | | PUSH |
:::success
Exemple. Pourquoi les `LOAD` sont sensibles ?
Dans le cas d’un hyperviseur de type 2, l’OS hôte a un IDTR, et l’OS invité en a un aussi, il faut être capable de distinguer les 2, changer de contexte et charger le bon IDTR en fonction du code qu’on exécute (charger / utiliser l’IDTR de l’OS hôte lorsque l’on exécute le code de l’hôte, et idem pour l’OS invité)
:::
On filtre donc les instructions pour savoir si on les laisse s'exécuter.

Ce filtre est placé sur le noyau, le superviseur ou le CPU.
### Le problème x86
Vu que x86 ne vérifie pas $\{sensibles\} \subset \{privilegiees\}$ il a fallu mettre le filtre à un autre endroit.
3 méthodes de tris
- 2 dites de “full virtualisation”
- 1 autre dite de “paravirtualisation”
### DIfférentes traductions :
**Binary translation** : première méthode de virtualisation du CPU:
- Proposé par VMWare au début
- Execution des VMs en ring 3 (l'OS ne sait pas qu'il est virtualisé)
- Gestion:
- interception des fautes renvoyées quand la VM tente de faire du privilégié
- Sensibles : on ne peut pas utiliser les fautes du processeur donc on doit décoder les instructions avant de les laisser passer.
- Performances *claquées au sol* puisqu’on fait des checks avant l’exécution de chaque instruction (ressemble à de l’émulation sauf qu’on finit par exécuter l’instruction telle quelle)
⇒ Plus utilisée aujourd’hui

**Full virtualization** : assistée par le matériel
- A mis un peu de temps (il fallait que les manufactureurs mettent à jour pour coller aux requirements)
- On met la VM en ring 0 mais en mode vmx_nonroot (autre mode que réel ou protégé)
- Ça permet pour le CPU de faire la différence entre les instructions de la machine host et les instructions de la VM
- Si la VM demande une instruction sensible on fait un VM_Exit qui rend la main au VMM (équivalent icall iret)
- L’OS est exécuté en Ring 0 et l’OS n’a pas conscience d’être virtualisé.
- Filtre au niveau du CPU

⇒ La solution utilisée en majorité ajd
Implémentation pratique :

Une VMCS par VM.
:::success
Exemple :
On essaye d’exécuter une instruction en mode non-root qui nécessiterait le mode root. Le CPU nous fait sortir du noyau pour que le VMM réalise ce qu’on veut (*VM_EXIT*). Une fois exécutée on revient en mode non_root (*VM_ENTRY*).

:::
Il faut donc rajouter des instructons supplémentaires :
- VMXON / VMXOFF pour entrer/sortir du mode hyperviseur
- Opérations de maintenance de la VM
- VMLaunch permet de lancer une VM

**Paravirtualization**
- l'OS sait qu'il est virtualisé, OS spécifique capable de fonctionner avec un hyperviseur
- Filtre à instructions dans le noyau de la VM, au lieu d'exécuter les instructions sensibles et privilégiées, elle fait des calls à l'hyperviseur (*hypercalls*) (e.g. au lieu de faire un `LIDT`, l’OS va faire un `CALL lidt_handler`)

:::info
*Xen* est historiquement un hyperviseur créé pour la paravirtualisation. Aujourd’hui il présente aussi des possibilités en Full virtualisation assistée par matériel (la deuxième).
:::
**Bilan :**
- Paravirtualisation est plus rapide que la Binary Translation, donc si t’as pas d’extension hardware (support matériel pour la virtualisation) alors la paravirtualisation c’est plus rapide si tu peux te permettre de préparer l’OS invité pour
- Si tu peux faire de la Full Virtualisation la question ne se pose pas, c’est la meilleure solution

### Nested Virtualization
- Hyperviseurs imbriqués
- virtualisation des instructions de virtualisation
- permet de débugger les VMM
## Virtualisation de la mémoire
Virtualiser la traduction des tables de pages :
- Shadow page tables (soft only)
- Nested page tables (hw assisted)
Dans les deux méthodes, y en a une qui doit etre AMD et l’autre Intel.
### Shadow Page Tables
**Exemple :** VM qui souhaite changer de processus et d'espace d'adressage
Lors de l’interception par le VMM, le CR3 en cours d’exécution est celui du VMM. On a pas envie qu’il soit écrasé.
Du coup le VMM crée un nouveau PGD et il met l’adresse de cette PGD dans le CR3 de la VM. *Pour la suite, cf slide du dessous.*
Le PGD vierge force à ce que la VM n’accède pas à une zone que le VMM ne souhaite pas. Parce que sinon on aurait donné direct l’adresse mémoire physique mappé à l’adresse virtuelle de la VMM et ça c’est pas foufou.
Le détail important ici le PF qui déclenche le process évoqué au-dessus. Là c’est l’hyperviseur qui gère la PGD de la VM.

### Nested Page Tables
La diff c’est que l’OS a un registre hardware supplémentaire : nested cr3.
Ici c’est le CPU qui fait la traduction de l’adresse VM vers l’adresse physique.

[https://youtu.be/SiVuXTqwYWk](https://youtu.be/SiVuXTqwYWk)
## Virtualisation des périphériques
- émulation
- pass-through : autoriser à dédier un périphérique à une VM
- périphériques modernes supportent la virtualisation
## Virtualisation et sécurité
Un hyperviseur c'est un logiciel donc on peut le tapper
:::warning
Vuln sur le logiciel hyperviseur, impact plus important que pour ue vuln sur l'OS
:::
### Surface d'attaque
- Désassemblage :
- instructions complexes de tailles variables
- Emulateur :
- instructions ring0
- exceptions
- périphériques
- ségrégation mémoire virtuelle/physique
### Outils de sécurité:
Utilisation de la virtualisation défensible :
- Virtualisation légère : micro-virtualisation
- Monitorer les droits en live
- Debugger un OS
- Protéger des programmes (isolation bac à sable)
**Exemples:**
- Protection de programmes → on peut considérer que l’OS est corrompue et on protège ce qu’il y a au-dessus
- Sandbox → virtualiser des applis à la volée pour les lancer
- Rootkit → c’est pas sympa, Blue Pill = Hyperviseur malveillant
- Controle des communications → BitVisor = Hyperviseur simplifié qui filtre certains flux genre il chiffre les données à la volée et laisse l’OS gérer les drivers
- HyperWall → protège flot infos inter machines
- OS COTS → SecVisor/Hytux sont complémentaires et servent à protéger le noyau au-dessus

Infos en vrac :
- Hyperviseur léger = peu de code, contrairement à OS COTS
- Pour filtrer les entrées vers le noyau, SecVisor se base sur une liste
- Hytux c’est le prof (lacombe) qui l’a fait
- Ce qui est bien avec la virtualisation c’est l’interception des comportements malveillants
- KCO = Kernel Contraint Object