From 05682b2bad45139c3bb81228ed3cbe38ba95b0fe Mon Sep 17 00:00:00 2001 From: Yonghua Huang Date: Thu, 12 Dec 2019 15:34:56 +0800 Subject: [PATCH] hv:bugfix in write protect page hypercall This patch fixes potential hypervisor crash when calling hcall_write_protect_page() with a crafted GPA in 'struct wp_data' instance, e.g. an invalid GPA that is not in the scope of the target VM's EPT address space. To check the validity for this GPA before updating the 'write protect' page. Tracked-On: #4240 Signed-off-by: Yonghua Huang Reviewed-by: Fei Li --- hypervisor/common/hypercall.c | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 8dcbb7d31..e8dbb9fb9 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -714,30 +714,34 @@ static int32_t write_protect_page(struct acrn_vm *vm,const struct wp_data *wp) uint64_t hpa, base_paddr; uint64_t prot_set; uint64_t prot_clr; - int32_t ret; + int32_t ret = -EINVAL; - hpa = gpa2hpa(vm, wp->gpa); - if (hpa == INVALID_HPA) { - pr_err("%s,vm[%hu] gpa 0x%lx,GPA is unmapping.", + if ((!mem_aligned_check(wp->gpa, PAGE_SIZE)) || + (!ept_is_mr_valid(vm, wp->gpa, PAGE_SIZE))) { + pr_err("%s,vm[%hu] gpa 0x%lx,GPA is invalid or not page size aligned.", __func__, vm->vm_id, wp->gpa); - ret = -EINVAL; } else { - dev_dbg(ACRN_DBG_HYCALL, "[vm%d] gpa=0x%x hpa=0x%x", + hpa = gpa2hpa(vm, wp->gpa); + if (hpa == INVALID_HPA) { + pr_err("%s,vm[%hu] gpa 0x%lx,GPA is unmapping.", + __func__, vm->vm_id, wp->gpa); + } else { + dev_dbg(ACRN_DBG_HYCALL, "[vm%d] gpa=0x%x hpa=0x%x", vm->vm_id, wp->gpa, hpa); - base_paddr = hva2hpa((void *)(get_hv_image_base())); - if (((hpa <= base_paddr) && ((hpa + PAGE_SIZE) > base_paddr)) || + base_paddr = hva2hpa((void *)(get_hv_image_base())); + if (((hpa <= base_paddr) && ((hpa + PAGE_SIZE) > base_paddr)) || ((hpa >= base_paddr) && (hpa < (base_paddr + CONFIG_HV_RAM_SIZE)))) { - pr_err("%s: overlap the HV memory region.", __func__); - ret = -EINVAL; - } else { - prot_set = (wp->set != 0U) ? 0UL : EPT_WR; - prot_clr = (wp->set != 0U) ? EPT_WR : 0UL; + pr_err("%s: overlap the HV memory region.", __func__); + } else { + prot_set = (wp->set != 0U) ? 0UL : EPT_WR; + prot_clr = (wp->set != 0U) ? EPT_WR : 0UL; - ept_modify_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, - wp->gpa, PAGE_SIZE, prot_set, prot_clr); - ret = 0; + ept_modify_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, + wp->gpa, PAGE_SIZE, prot_set, prot_clr); + ret = 0; + } } }