Skip to content

Commit 57bf26d

Browse files
yonghuahwenlingz
authored andcommitted
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>
1 parent 73ab727 commit 57bf26d

File tree

5 files changed

+101
-98
lines changed

5 files changed

+101
-98
lines changed

hypervisor/arch/x86/assign.c

Lines changed: 63 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,8 @@ static void activate_physical_ioapic(struct acrn_vm *vm,
628628
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
629629
enum ptirq_vpin_source vpin_src)
630630
{
631-
struct ptirq_remapping_info *entry;
631+
int32_t status = 0;
632+
struct ptirq_remapping_info *entry = NULL;
632633
bool need_switch_vpin_src = false;
633634
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src);
634635
bool pic_pin = (vpin_src == PTDEV_VPIN_PIC);
@@ -647,80 +648,80 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
647648
/* no remap for hypervisor owned intx */
648649
#ifdef CONFIG_COM_IRQ
649650
if (ptdev_hv_owned_intx(vm, &virt_sid)) {
650-
goto END;
651+
status = -ENODEV;
651652
}
652653
#endif /* CONFIG_COM_IRQ */
653654

654-
/* query if we have virt to phys mapping */
655-
spinlock_obtain(&ptdev_lock);
656-
entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
657-
if (entry == NULL) {
658-
if (is_vm0(vm)) {
659-
660-
/* for vm0, there is chance of vpin source switch
661-
* between vPIC & vIOAPIC for one legacy phys_pin.
662-
*
663-
* here checks if there is already mapping entry from
664-
* the other vpin source for legacy pin. If yes, then
665-
* switch vpin source is needed
666-
*/
667-
if (virt_pin < NR_LEGACY_PIN) {
668-
uint8_t vpin = pic_ioapic_pin_map[virt_pin];
669-
670-
entry = ptirq_lookup_entry_by_vpin(vm, vpin, !pic_pin);
671-
if (entry != NULL) {
672-
need_switch_vpin_src = true;
655+
if (status || (pic_pin && (virt_pin >= NR_VPIC_PINS_TOTAL))) {
656+
status = -EINVAL;
657+
} else {
658+
/* query if we have virt to phys mapping */
659+
spinlock_obtain(&ptdev_lock);
660+
entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
661+
if (entry == NULL) {
662+
if (is_vm0(vm)) {
663+
664+
/* for vm0, there is chance of vpin source switch
665+
* between vPIC & vIOAPIC for one legacy phys_pin.
666+
*
667+
* here checks if there is already mapping entry from
668+
* the other vpin source for legacy pin. If yes, then
669+
* switch vpin source is needed
670+
*/
671+
if (virt_pin < NR_LEGACY_PIN) {
672+
uint8_t vpin = pic_ioapic_pin_map[virt_pin];
673+
674+
entry = ptirq_lookup_entry_by_vpin(vm, vpin, !pic_pin);
675+
if (entry != NULL) {
676+
need_switch_vpin_src = true;
677+
}
673678
}
674-
}
675-
676-
/* entry could be updated by above switch check */
677-
if (entry == NULL) {
678-
uint8_t phys_pin = virt_pin;
679679

680-
/* fix vPIC pin to correct native IOAPIC pin */
681-
if (pic_pin) {
682-
phys_pin = pic_ioapic_pin_map[virt_pin];
683-
}
684-
entry = add_intx_remapping(vm,
685-
virt_pin, phys_pin, pic_pin);
680+
/* entry could be updated by above switch check */
686681
if (entry == NULL) {
687-
pr_err("%s, add intx remapping failed",
688-
__func__);
689-
spinlock_release(&ptdev_lock);
690-
return -ENODEV;
682+
uint8_t phys_pin = virt_pin;
683+
684+
/* fix vPIC pin to correct native IOAPIC pin */
685+
if (pic_pin) {
686+
phys_pin = pic_ioapic_pin_map[virt_pin];
687+
}
688+
entry = add_intx_remapping(vm,
689+
virt_pin, phys_pin, pic_pin);
690+
if (entry == NULL) {
691+
pr_err("%s, add intx remapping failed",
692+
__func__);
693+
status = -ENODEV;
694+
}
691695
}
696+
} else {
697+
/* ptirq_intx_pin_remap is triggered by vPIC/vIOAPIC
698+
* everytime a pin get unmask, here filter out pins
699+
* not get mapped.
700+
*/
701+
status = -ENODEV;
692702
}
693-
} else {
694-
/* ptirq_intx_pin_remap is triggered by vPIC/vIOAPIC
695-
* everytime a pin get unmask, here filter out pins
696-
* not get mapped.
697-
*/
698-
spinlock_release(&ptdev_lock);
699-
goto END;
700703
}
704+
spinlock_release(&ptdev_lock);
701705
}
702706

703-
/* if vpin source need switch */
704-
if (need_switch_vpin_src) {
705-
dev_dbg(ACRN_DBG_IRQ,
706-
"IOAPIC pin=%hhu pirq=%u vpin=%d switch from %s to %s "
707-
"vpin=%d for vm%d", entry->phys_sid.intx_id.pin,
708-
entry->allocated_pirq, entry->virt_sid.intx_id.pin,
709-
(vpin_src == 0)? "vPIC" : "vIOAPIC",
710-
(vpin_src == 0)? "vIOPIC" : "vPIC",
711-
virt_pin, entry->vm->vm_id);
712-
entry->virt_sid.value = virt_sid.value;
707+
if (!status) {
708+
spinlock_obtain(&ptdev_lock);
709+
/* if vpin source need switch */
710+
if ((need_switch_vpin_src) && (entry != NULL)) {
711+
dev_dbg(ACRN_DBG_IRQ,
712+
"IOAPIC pin=%hhu pirq=%u vpin=%d switch from %s to %s vpin=%d for vm%d",
713+
entry->phys_sid.intx_id.pin,
714+
entry->allocated_pirq, entry->virt_sid.intx_id.pin,
715+
(vpin_src == 0) ? "vPIC" : "vIOAPIC",
716+
(vpin_src == 0) ? "vIOPIC" : "vPIC",
717+
virt_pin, entry->vm->vm_id);
718+
entry->virt_sid.value = virt_sid.value;
719+
}
720+
spinlock_release(&ptdev_lock);
721+
activate_physical_ioapic(vm, entry);
713722
}
714-
spinlock_release(&ptdev_lock);
715723

716-
activate_physical_ioapic(vm, entry);
717-
dev_dbg(ACRN_DBG_IRQ,
718-
"IOAPIC pin=%hhu pirq=%u assigned to vm%d %s vpin=%d",
719-
entry->phys_sid.intx_id.pin, entry->allocated_pirq,
720-
entry->vm->vm_id, vpin_src == PTDEV_VPIN_PIC ?
721-
"vPIC" : "vIOAPIC", virt_pin);
722-
END:
723-
return 0;
724+
return status;
724725
}
725726

726727
/* @pre vm != NULL

hypervisor/arch/x86/cpu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ void init_cpu_pre(uint16_t pcpu_id)
407407
early_init_lapic();
408408

409409
pcpu_id = get_cpu_id_from_lapic_id(get_cur_lapic_id());
410+
if (pcpu_id >= CONFIG_MAX_PCPU_NUM) {
411+
panic("Invalid pCPU ID!");
412+
}
410413
}
411414

412415
bitmap_set_nolock(pcpu_id, &pcpu_active_bitmap);

hypervisor/common/hypercall.c

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,46 +1049,44 @@ int32_t hcall_get_cpu_pm_state(struct acrn_vm *vm, uint64_t cmd, uint64_t param)
10491049
*/
10501050
int32_t hcall_vm_intr_monitor(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
10511051
{
1052+
int32_t status = -EINVAL;
10521053
struct acrn_intr_monitor *intr_hdr;
10531054
uint64_t hpa;
10541055
struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
10551056

1056-
if (target_vm == NULL) {
1057-
return -1;
1058-
}
1059-
1060-
/* the param for this hypercall is page aligned */
1061-
hpa = gpa2hpa(vm, param);
1062-
if (hpa == INVALID_HPA) {
1063-
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
1064-
__func__, vm->vm_id, param);
1065-
return -EINVAL;
1066-
}
1067-
1068-
intr_hdr = (struct acrn_intr_monitor *)hpa2hva(hpa);
1069-
1070-
stac();
1071-
switch (intr_hdr->cmd) {
1072-
case INTR_CMD_GET_DATA:
1073-
intr_hdr->buf_cnt = ptirq_get_intr_data(target_vm,
1074-
intr_hdr->buffer, intr_hdr->buf_cnt);
1075-
break;
1076-
1077-
case INTR_CMD_DELAY_INT:
1078-
/* buffer[0] is the delay time (in MS), if 0 to cancel delay */
1079-
target_vm->intr_inject_delay_delta =
1080-
intr_hdr->buffer[0] * CYCLES_PER_MS;
1081-
break;
1082-
1083-
default:
1084-
/* if cmd wrong it goes here should not happen */
1085-
break;
1057+
if (target_vm != NULL) {
1058+
1059+
/* the param for this hypercall is page aligned */
1060+
hpa = gpa2hpa(vm, param);
1061+
if (hpa != INVALID_HPA) {
1062+
intr_hdr = (struct acrn_intr_monitor *)hpa2hva(hpa);
1063+
stac();
1064+
if (intr_hdr->buf_cnt <= (MAX_PTDEV_NUM * 2U)) {
1065+
switch (intr_hdr->cmd) {
1066+
case INTR_CMD_GET_DATA:
1067+
intr_hdr->buf_cnt = ptirq_get_intr_data(target_vm,
1068+
intr_hdr->buffer, intr_hdr->buf_cnt);
1069+
break;
1070+
1071+
case INTR_CMD_DELAY_INT:
1072+
/* buffer[0] is the delay time (in MS), if 0 to cancel delay */
1073+
target_vm->intr_inject_delay_delta =
1074+
intr_hdr->buffer[0] * CYCLES_PER_MS;
1075+
break;
1076+
1077+
default:
1078+
/* if cmd wrong it goes here should not happen */
1079+
break;
1080+
}
1081+
1082+
status = 0;
1083+
pr_dbg("intr monitor:%d, cnt=%d", intr_hdr->cmd, intr_hdr->buf_cnt);
1084+
}
1085+
clac();
1086+
}
10861087
}
10871088

1088-
pr_dbg("intr monitor:%d, cnt=%d", intr_hdr->cmd, intr_hdr->buf_cnt);
1089-
clac();
1090-
1091-
return 0;
1089+
return status;
10921090
}
10931091

10941092
/**

hypervisor/common/ptdev.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ void ptirq_release_entry(struct ptirq_remapping_info *entry)
123123
list_del_init(&entry->softirq_node);
124124
spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags);
125125
atomic_clear32(&entry->active, ACTIVE_FLAG);
126-
bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU, &ptirq_entry_bitmaps[(entry->ptdev_entry_id) >> 6U]);
126+
bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU,
127+
&ptirq_entry_bitmaps[((entry->ptdev_entry_id) & 0x3FU) >> 6U]);
127128
}
128129

129130
/* interrupt context */

hypervisor/include/public/acrn_common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ enum pm_cmd_type {
626626
*
627627
* the parameter for HC_VM_INTR_MONITOR hypercall
628628
*/
629-
#define MAX_PTDEV_NUM 24
629+
#define MAX_PTDEV_NUM 24U
630630
struct acrn_intr_monitor {
631631
/** sub command for intr monitor */
632632
uint32_t cmd;

0 commit comments

Comments
 (0)