Exploit-DB #43014
Description: Xen - Pagetable De-typing Unbounded Recursion
Type: dos
Platform: linux
Date: 2017-10-18
Author: Google Security Research

Exploit:
Xen allows pagetables of the same level to map each other as readonly
in PV domains. This is useful if a guest wants to use the
self-referential pagetable trick for easy access to pagetables
by mapped virtual address.

When cleaning up a pagetable after the last typed reference to it has been
dropped (via __put_page_type() -> __put_final_page_type() -> free_page_type()),
Xen will recursively drop the typed refcounts of pages referenced by the pagetable,
potentially recursively cleaning them up as well.
For normal pagetables, the recursion depth is bounded by the number of paging levels
the architecture supports. However, no such depth limit exists for pagetables of the
same depth that map each other.

The attached PoC will set up a chain of 1000 L4 pagetables such that
the first pagetable is type-pinned and each following pagetable is referenced by the
previous one. Then, the type-pin of the first pagetable is removed, and the following
999 pagetables are recursively cleaned up, causing a stack overflow.

To run the PoC in a PV domain, install kernel headers, then run ./compile, then load the built module via insmod.

Xen console output caused by running the PoC inside a normal PV domain:

==============================
(XEN) Xen version 4.8.1 (Debian 4.8.1-1+deb9u3) (ian.jackson@eu.citrix.com) (gcc (Debian 6.3.0-18) 6.3.0 20170516) debug=n  Thu Sep  7 18:24:26 UTC 2017
(XEN) Bootloader: GRUB 2.02~beta3-5
(XEN) Command line: loglvl=all com1=115200,8n1,pci console=com1 placeholder
(XEN) Video information:
(XEN)  VGA is text mode 80x25, font 8x16
(XEN) Disc information:
(XEN)  Found 1 MBR signatures
(XEN)  Found 1 EDD information structures
(XEN) Xen-e820 RAM map:
(XEN)  [PII_REDACTED] -[PII_REDACTED]09fc00 (usable)
(XEN) [PII_REDACTED]09fc00 -[PII_REDACTED]0a0000 (reserved)
(XEN) [PII_REDACTED]0f0000 - [PII_REDACTED] (reserved)
(XEN)  [PII_REDACTED] - 00000000dfff0000 (usable)
(XEN)  00000000dfff0000 - 00000000e0000000 (ACPI data)
(XEN)  00000000fec00000 - 00000000fec01000 (reserved)
(XEN)  00000000fee00000 - 00000000fee01000 (reserved)
(XEN)  00000000fffc0000 - [PII_REDACTED] (reserved)
(XEN)  [PII_REDACTED] - [PII_REDACTED] (usable)
(XEN) ACPI: RSDP 000E0000, 0024 (r2 VBOX  )
(XEN) ACPI: XSDT DFFF0030, 003C (r1 VBOX   VBOXXSDT        1 ASL        61)
(XEN) ACPI: FACP DFFF00F0, 00F4 (r4 VBOX   VBOXFACP        1 ASL        61)
(XEN) ACPI: DSDT DFFF0470, 210F (r1 VBOX   VBOXBIOS        2 INTL 20140214)
(XEN) ACPI: FACS DFFF0200, 0040
(XEN) ACPI: APIC DFFF0240, 0054 (r2 VBOX   VBOXAPIC        1 ASL        61)
(XEN) ACPI: SSDT DFFF02A0, 01CC (r1 VBOX   VBOXCPUT        2 INTL 20140214)
(XEN) System RAM: 4095MB (4193852kB)
(XEN) No NUMA configuration found
(XEN) Faking a node at [PII_REDACTED]-[PII_REDACTED]
(XEN) Domain heap initialised
(XEN) CPU Vendor: Intel, Family 6 (0x6), Model 78 (0x4e), Stepping 3 (raw 000406e3)
(XEN) found SMP MP-table at 0009fff0
(XEN) DMI 2.5 present.
(XEN) Using APIC driver default
(XEN) ACPI: PM-Timer IO Port: 0x4008 (32 bits)
(XEN) ACPI: SLEEP INFO: pm1x_cnt[1:4004,1:0], pm1x_evt[1:4000,1:0]
(XEN) ACPI:             wakeup_vec[dfff020c], vec_size[20]
(XEN) ACPI: Local APIC address 0xfee00000
(XEN) ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
(XEN) ACPI: IOAPIC (id[0x01] address[0xfec00000] gsi_base[0])
(XEN) IOAPIC[0]: apic_id 1, version 32, address 0xfec00000, GSI 0-23
(XEN) ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
(XEN) ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
(XEN) ACPI: IRQ0 used by override.
(XEN) ACPI: IRQ2 used by override.
(XEN) ACPI: IRQ9 used by override.
(XEN) Enabling APIC mode:  Flat.  Using 1 I/O APICs
(XEN) ERST table was not found
(XEN) Using ACPI (MADT) for SMP configuration information
(XEN) SMP: Allowing 1 CPUs (0 hotplug CPUs)
(XEN) IRQ limits: 24 GSI, 184 MSI/MSI-X
(XEN) Not enabling x2APIC: depends on iommu_supports_eim.
(XEN) xstate: size: 0x440 and states: 0x7
(XEN) CPU0: No MCE banks present. Machine check support disabled
(XEN) Using scheduler: SMP Credit Scheduler (credit)
(XEN) Platform timer is 3.579MHz ACPI PM Timer
(XEN) Detected 2807.850 MHz processor.
(XEN) Initing memory sharing.
(XEN) alt table ffff82d0802bcf38 -> ffff82d0802be594
(XEN) I/O virtualisation disabled
(XEN) nr_sockets: 1
(XEN) ENABLING IO-APIC IRQs
(XEN)  -> Using new ACK method
(XEN) ..TIMER: vector=0xF0 apic1=0 pin1=2 apic2=-1 pin2=-1
(XEN) Allocated console ring of 16 KiB.
(XEN) Brought up 1 CPUs
(XEN) build-id: cd504b2b380e2fe1265376aa845a404b9eb86982
(XEN) CPUIDLE: disabled due to no HPET. Force enable with 'cpuidle'.
(XEN) ACPI sleep modes: S3
(XEN) VPMU: disabled
(XEN) xenoprof: Initialization failed. Intel processor family 6 model 78is not supported
(XEN) Dom0 has maximum 208 PIRQs
(XEN) NX (Execute Disable) protection active
(XEN) *** LOADING DOMAIN 0 ***
(XEN)  Xen  kernel: 64-bit, lsb, compat32
(XEN)  Dom0 kernel: 64-bit, PAE, lsb, paddr 0x1000000 -> 0x1f5a000
(XEN) PHYSICAL MEMORY ARRANGEMENT:
(XEN)  Dom0 alloc.:   [PII_REDACTED]->000000011a000000 (989666 pages to be allocated)
(XEN)  Init. ramdisk: 000000011ed74000->000000011ffff3b5
(XEN) VIRTUAL MEMORY ARRANGEMENT:
(XEN)  Loaded kernel: ffffffff81000000->ffffffff81f5a000
(XEN)  Init. ramdisk: [PII_REDACTED]->[PII_REDACTED]
(XEN)  Phys-Mach map: [PII_REDACTED]->[PII_REDACTED]7a6370
(XEN)  Start info:    ffffffff81f5a000->ffffffff81f5a4b4
(XEN)  Page tables:   ffffffff81f5b000->ffffffff81f6e000
(XEN)  Boot stack:    ffffffff81f6e000->ffffffff81f6f000
(XEN)  TOTAL:         ffffffff80000000->ffffffff82000000
(XEN)  ENTRY ADDRESS: ffffffff81d38180
(XEN) Dom0 has maximum 1 VCPUs
(XEN) Scrubbing Free RAM on 1 nodes using 1 CPUs
(XEN) ....................................done.
(XEN) Initial low memory virq threshold set at 0x4000 pages.
(XEN) Std. Loglevel: All
(XEN) Guest Loglevel: Nothing (Rate-limited: Errors and warnings)
(XEN) *** Serial input -