When shutting down the hypervisor, in the leave_hypervisor
function, the Linux driver touches every hypervisor page, to
ensure all pages are mapped. However, the current implementation
assumes hv_core_and_percpu_size is aligned to PAGE_SIZE. This may
not be the case, if PAGE_SIZE is different on the hypervisor side.
This can cause an unsigned long overflow, leading to an infinite
loop of touching successive pages starting from hypervisor_mem.
The loop will be broken as soon as Linux tries to touch an invalid
page, leading to a kernel crash.
Signed-off-by: Antonios Motakis <antonios.motakis@huawei.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
static void leave_hypervisor(void *info)
{
- unsigned long size;
void *page;
int err;
/* Touch each hypervisor page we may need during the switch so that
* the active mm definitely contains all mappings. At least x86 does
* not support taking any faults while switching worlds. */
- for (page = hypervisor_mem, size = hv_core_and_percpu_size; size > 0;
- size -= PAGE_SIZE, page += PAGE_SIZE)
+ for (page = hypervisor_mem;
+ page < hypervisor_mem + hv_core_and_percpu_size;
+ page += PAGE_SIZE)
readl((void __iomem *)page);
/* either returns 0 or the same error code across all CPUs */