Xen: Probleme mit virtuellem Speicher bei 64-Bit Gastsystemen

Xen ist eine freie Hypervisor-Lösung, die den Betrieb mehrerer virtueller Maschinen auf einem Host erlaubt. Eine Schwachstelle in einem Makro zur Prüfung virtueller Speicheradressen hat zur Folge, dass ein Gast-Administrator das Host-System zum Absturz bringen kann.

Linux-Anwendungen verwenden Syscalls, um mit dem Linux Kernel zu kommunizieren, wobei der Kernel selbst auf der Ring-0-Ebene des Systems läuft. Unter Xen allerdings läuft der Hypervisor in Ring 0, während die Gastsysteme meist in Ring 1 ablaufen. Um dem Gastsystem Zugriff auf Hypervisor-Dienste zu erlauben, implementiert Xen so genannte Hypercalls. Diese sind das Pendant zu Syscalls, die ebenfalls durch Interrupt 0x82 ausgelöst werden können. In beiden Fällen wird die Syscall/Hypercall-Nummer im EAX-Register vor dem Interrupt-Aufruf abgelegt. Hypercalls geben die Ausführungskontrolle von Ring 1 an den Ring 0 weiter, in dem der Hypervisor läuft.

Eine Liste verfügbarer Hypercalls findet sich in der Include-Datei “xen/include/public/xen.h”:

/* * HYPERCALLS */
#define __HYPERVISOR_set_trap_table 0
#define __HYPERVISOR_mmu_update 1
#define __HYPERVISOR_set_gdt 2
#define __HYPERVISOR_stack_switch 3
#define __HYPERVISOR_set_callbacks 4
#define __HYPERVISOR_fpu_taskswitch 5
#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
#define __HYPERVISOR_platform_op 7
#define __HYPERVISOR_set_debugreg 8
...

Bei einem Hypercall-Wechsel von Ring 1 nach Ring 0 (und auch einem gewöhnlichen Systemcall-Wechsel von Userspace zum Kernelspace) ist es wichtig, die Speichertrennung der verschiedenen Bereiche zu beachten. So kann der Userspace nicht direkt auf Kernelspace zugreifen und umgekehrt. Genauso verhält es sich auch bei dem Zugriff auf Hypervisor-Ressourcen vom Gastsystem aus.

Linux verwendet wie die meisten modernen Betriebssysteme virtuelle Speicherbereiche und abstrahiert damit von physikalischen Speicheradressen. Auf einem 32-Bit System hat das System damit einen 4 GByte großen virtuellen Speicherbereich zur Verfügung. Der virtuelle Speicher ist typischerweise in Pages aufgeteilt, die auf Pages im physikalischen Speicher oder aber Auslagerungsdateien abgebildet werden können. Diese Abbildung wird von der Seitentabelle bereitgestellt und von der Memory Management Unit (MMU) durchgeführt. 64-Bit Systeme haben einen virtuellen Adressraum, der derzeit 48 Bit groß ist, obwohl die Zeiger selbst volle 64 Bit breit sind.

Unter Xen stehen allerdings nicht die vollen 48 Bit zur Verfügungen, sondern lediglich 47 Bit, da der Rest für Xen reserviert ist. Es ist also wichtig, beim Verarbeiten von Speicheradressen sicherzustellen, dass diese Speichergrenze nicht überschritten wird. Dazu verwendet Xen ein Makro namens ” __addr_ok()”, das in der Datei “/xen/include/asm-x86/x86_64/uaccess.h” definiert ist:

/* * Valid if in +ve half of 48-bit address space, or above Xen-reserved area. * This is also valid for range checks (addr, addr+size). As long as the * start address is outside the Xen-reserved area then we will access a * non-canonical address (and thus fault) before ever reaching VIRT_START. */
#define __addr_ok(addr) \ (((unsigned long)(addr) < (1UL<<48)) || \ ((unsigned long)(addr) >= HYPERVISOR_VIRT_END))

Dieses Makro prüft die Zeiger-Adresse und liefert True, falls der Zeiger in Ordnung ist und die Speichergrenzen nicht verletzt. Wer genau hinsieht, erkennt hier eine Bitshift-Operation, die eine 1 um 48 Stellen nach links schiebt und das Ergebnis dann mit der Adresse “addr” vergleicht. Dies ist aber nicht ganz richtig, da lediglich 47 Bit zur Verfügung stehen. Das kann zur Folge haben, dass ein lokaler Angreifer auf dem Gastsystem unzulässige Speicherzugriffe durchführen kann und so das Hostsystem zum Absturz bringt. Die Korrektur dieses Fehlers sieht folgendermaßen aus:

#define __addr_ok(addr) \ (((unsigned long)(addr) < (1UL<<47)) || \ ((unsigned long)(addr) >= HYPERVISOR_VIRT_END))

Die 48 muss also einfach durch eine 47 ersetzt werden, wodurch der korrekte Speicherbereich geprüft wird.

Betroffen von dieser Schwachstelle ist die Xen-Version 3.3, falls 64-Bit-Gastsysteme zum Einsatz kommen.

Nach oben