hv:bugfix in write protect page hypercall

This patch fixes potential hypervisor crash when calling
 hc_hcall_write_protect_page()with a crafted GPA in
 'struct wp_data' instance, e.g. an invalid GPA that is
 out of the scope of target VM's EPT address space.

Tracked-On: #4669
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
This commit is contained in:
Yonghua Huang 2020-04-20 09:42:57 +08:00 committed by wenlingz
parent 66d824d677
commit 2e9028128f
3 changed files with 33 additions and 0 deletions

View File

@ -10,6 +10,19 @@
#define ACRN_DBG_EPT 6U #define ACRN_DBG_EPT 6U
bool ept_is_mr_valid(const struct acrn_vm *vm, uint64_t base, uint64_t size)
{
bool valid = true;
uint64_t end = base + size;
uint64_t top_address_space = vm->arch_vm.ept_mem_ops.info->ept.top_address_space;
if ((end <= base) || (end > top_address_space)) {
valid = false;
}
return valid;
}
void destroy_ept(struct acrn_vm *vm) void destroy_ept(struct acrn_vm *vm)
{ {
/* Destroy secure world */ /* Destroy secure world */

View File

@ -635,6 +635,13 @@ static int32_t write_protect_page(struct acrn_vm *vm,const struct wp_data *wp)
uint64_t prot_set; uint64_t prot_set;
uint64_t prot_clr; uint64_t prot_clr;
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);
return -EINVAL;
}
hpa = gpa2hpa(vm, wp->gpa); hpa = gpa2hpa(vm, wp->gpa);
if (hpa == INVALID_HPA) { if (hpa == INVALID_HPA) {
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.", pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",

View File

@ -219,6 +219,19 @@ static inline void clflush(volatile void *p)
#define INVALID_HPA (0x1UL << 52U) #define INVALID_HPA (0x1UL << 52U)
#define INVALID_GPA (0x1UL << 52U) #define INVALID_GPA (0x1UL << 52U)
/* External Interfaces */ /* External Interfaces */
/**
* @brief Check guest-physical memory region mapping valid
*
* @param[in] vm the pointer that points to VM data structure
* @param[in] base The specified start guest physical address of guest
* physical memory region
* @param[in] size The size of guest physical memory region
*
* @retval true if the guest-physical memory region mapping valid, false otherwise.
*/
bool ept_is_mr_valid(const struct acrn_vm *vm, uint64_t base, uint64_t size);
/** /**
* @brief EPT page tables destroy * @brief EPT page tables destroy
* *