hv: fix possible buffer overflow issues

- cpu_secondary_init() @cpu.c
 - ptirq_intx_pin_remap() @ assign.c
   etc.

Tracked-On: #1252
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yonghua Huang 2018-12-14 00:03:52 +08:00 committed by wenlingz
parent 73ab727434
commit 57bf26dc17
5 changed files with 99 additions and 96 deletions

View File

@ -628,7 +628,8 @@ static void activate_physical_ioapic(struct acrn_vm *vm,
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin, int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
enum ptirq_vpin_source vpin_src) enum ptirq_vpin_source vpin_src)
{ {
struct ptirq_remapping_info *entry; int32_t status = 0;
struct ptirq_remapping_info *entry = NULL;
bool need_switch_vpin_src = false; bool need_switch_vpin_src = false;
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src); DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src);
bool pic_pin = (vpin_src == PTDEV_VPIN_PIC); bool pic_pin = (vpin_src == PTDEV_VPIN_PIC);
@ -647,10 +648,13 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
/* no remap for hypervisor owned intx */ /* no remap for hypervisor owned intx */
#ifdef CONFIG_COM_IRQ #ifdef CONFIG_COM_IRQ
if (ptdev_hv_owned_intx(vm, &virt_sid)) { if (ptdev_hv_owned_intx(vm, &virt_sid)) {
goto END; status = -ENODEV;
} }
#endif /* CONFIG_COM_IRQ */ #endif /* CONFIG_COM_IRQ */
if (status || (pic_pin && (virt_pin >= NR_VPIC_PINS_TOTAL))) {
status = -EINVAL;
} else {
/* query if we have virt to phys mapping */ /* query if we have virt to phys mapping */
spinlock_obtain(&ptdev_lock); spinlock_obtain(&ptdev_lock);
entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin); entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
@ -686,8 +690,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
if (entry == NULL) { if (entry == NULL) {
pr_err("%s, add intx remapping failed", pr_err("%s, add intx remapping failed",
__func__); __func__);
spinlock_release(&ptdev_lock); status = -ENODEV;
return -ENODEV;
} }
} }
} else { } else {
@ -695,32 +698,30 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
* everytime a pin get unmask, here filter out pins * everytime a pin get unmask, here filter out pins
* not get mapped. * not get mapped.
*/ */
spinlock_release(&ptdev_lock); status = -ENODEV;
goto END;
} }
} }
spinlock_release(&ptdev_lock);
}
if (!status) {
spinlock_obtain(&ptdev_lock);
/* if vpin source need switch */ /* if vpin source need switch */
if (need_switch_vpin_src) { if ((need_switch_vpin_src) && (entry != NULL)) {
dev_dbg(ACRN_DBG_IRQ, dev_dbg(ACRN_DBG_IRQ,
"IOAPIC pin=%hhu pirq=%u vpin=%d switch from %s to %s " "IOAPIC pin=%hhu pirq=%u vpin=%d switch from %s to %s vpin=%d for vm%d",
"vpin=%d for vm%d", entry->phys_sid.intx_id.pin, entry->phys_sid.intx_id.pin,
entry->allocated_pirq, entry->virt_sid.intx_id.pin, entry->allocated_pirq, entry->virt_sid.intx_id.pin,
(vpin_src == 0)? "vPIC" : "vIOAPIC", (vpin_src == 0) ? "vPIC" : "vIOAPIC",
(vpin_src == 0)? "vIOPIC" : "vPIC", (vpin_src == 0) ? "vIOPIC" : "vPIC",
virt_pin, entry->vm->vm_id); virt_pin, entry->vm->vm_id);
entry->virt_sid.value = virt_sid.value; entry->virt_sid.value = virt_sid.value;
} }
spinlock_release(&ptdev_lock); spinlock_release(&ptdev_lock);
activate_physical_ioapic(vm, entry); activate_physical_ioapic(vm, entry);
dev_dbg(ACRN_DBG_IRQ, }
"IOAPIC pin=%hhu pirq=%u assigned to vm%d %s vpin=%d",
entry->phys_sid.intx_id.pin, entry->allocated_pirq, return status;
entry->vm->vm_id, vpin_src == PTDEV_VPIN_PIC ?
"vPIC" : "vIOAPIC", virt_pin);
END:
return 0;
} }
/* @pre vm != NULL /* @pre vm != NULL

View File

@ -407,6 +407,9 @@ void init_cpu_pre(uint16_t pcpu_id)
early_init_lapic(); early_init_lapic();
pcpu_id = get_cpu_id_from_lapic_id(get_cur_lapic_id()); pcpu_id = get_cpu_id_from_lapic_id(get_cur_lapic_id());
if (pcpu_id >= CONFIG_MAX_PCPU_NUM) {
panic("Invalid pCPU ID!");
}
} }
bitmap_set_nolock(pcpu_id, &pcpu_active_bitmap); bitmap_set_nolock(pcpu_id, &pcpu_active_bitmap);

View File

@ -1049,25 +1049,19 @@ int32_t hcall_get_cpu_pm_state(struct acrn_vm *vm, uint64_t cmd, uint64_t param)
*/ */
int32_t hcall_vm_intr_monitor(struct acrn_vm *vm, uint16_t vmid, uint64_t param) int32_t hcall_vm_intr_monitor(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
{ {
int32_t status = -EINVAL;
struct acrn_intr_monitor *intr_hdr; struct acrn_intr_monitor *intr_hdr;
uint64_t hpa; uint64_t hpa;
struct acrn_vm *target_vm = get_vm_from_vmid(vmid); struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
if (target_vm == NULL) { if (target_vm != NULL) {
return -1;
}
/* the param for this hypercall is page aligned */ /* the param for this hypercall is page aligned */
hpa = gpa2hpa(vm, param); hpa = gpa2hpa(vm, param);
if (hpa == INVALID_HPA) { if (hpa != INVALID_HPA) {
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
__func__, vm->vm_id, param);
return -EINVAL;
}
intr_hdr = (struct acrn_intr_monitor *)hpa2hva(hpa); intr_hdr = (struct acrn_intr_monitor *)hpa2hva(hpa);
stac(); stac();
if (intr_hdr->buf_cnt <= (MAX_PTDEV_NUM * 2U)) {
switch (intr_hdr->cmd) { switch (intr_hdr->cmd) {
case INTR_CMD_GET_DATA: case INTR_CMD_GET_DATA:
intr_hdr->buf_cnt = ptirq_get_intr_data(target_vm, intr_hdr->buf_cnt = ptirq_get_intr_data(target_vm,
@ -1085,10 +1079,14 @@ int32_t hcall_vm_intr_monitor(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
break; break;
} }
status = 0;
pr_dbg("intr monitor:%d, cnt=%d", intr_hdr->cmd, intr_hdr->buf_cnt); pr_dbg("intr monitor:%d, cnt=%d", intr_hdr->cmd, intr_hdr->buf_cnt);
}
clac(); clac();
}
}
return 0; return status;
} }
/** /**

View File

@ -123,7 +123,8 @@ void ptirq_release_entry(struct ptirq_remapping_info *entry)
list_del_init(&entry->softirq_node); list_del_init(&entry->softirq_node);
spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags); spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags);
atomic_clear32(&entry->active, ACTIVE_FLAG); atomic_clear32(&entry->active, ACTIVE_FLAG);
bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU, &ptirq_entry_bitmaps[(entry->ptdev_entry_id) >> 6U]); bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU,
&ptirq_entry_bitmaps[((entry->ptdev_entry_id) & 0x3FU) >> 6U]);
} }
/* interrupt context */ /* interrupt context */

View File

@ -626,7 +626,7 @@ enum pm_cmd_type {
* *
* the parameter for HC_VM_INTR_MONITOR hypercall * the parameter for HC_VM_INTR_MONITOR hypercall
*/ */
#define MAX_PTDEV_NUM 24 #define MAX_PTDEV_NUM 24U
struct acrn_intr_monitor { struct acrn_intr_monitor {
/** sub command for intr monitor */ /** sub command for intr monitor */
uint32_t cmd; uint32_t cmd;