Commit 080e8d2e authored by Bibo Mao's avatar Bibo Mao Committed by Huacai Chen
Browse files

LoongArch: KVM: Avoid overflow with array index



The variable index is modified and reused as array index when modify
register EIOINTC_ENABLE. There will be array index overflow problem.

Cc: stable@vger.kernel.org
Fixes: 3956a52b ("LoongArch: KVM: Add EIOINTC read and write functions")
Signed-off-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent a0137c90
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -436,17 +436,16 @@ static int loongarch_eiointc_writew(struct kvm_vcpu *vcpu,
		break;
	case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
		index = (offset - EIOINTC_ENABLE_START) >> 1;
		old_data = s->enable.reg_u32[index];
		old_data = s->enable.reg_u16[index];
		s->enable.reg_u16[index] = data;
		/*
		 * 1: enable irq.
		 * update irq when isr is set.
		 */
		data = s->enable.reg_u16[index] & ~old_data & s->isr.reg_u16[index];
		index = index << 1;
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index + i, mask, 1);
			eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 1);
		}
		/*
		 * 0: disable irq.
@@ -455,7 +454,7 @@ static int loongarch_eiointc_writew(struct kvm_vcpu *vcpu,
		data = ~s->enable.reg_u16[index] & old_data & s->isr.reg_u16[index];
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index, mask, 0);
			eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 0);
		}
		break;
	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
@@ -529,10 +528,9 @@ static int loongarch_eiointc_writel(struct kvm_vcpu *vcpu,
		 * update irq when isr is set.
		 */
		data = s->enable.reg_u32[index] & ~old_data & s->isr.reg_u32[index];
		index = index << 2;
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index + i, mask, 1);
			eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 1);
		}
		/*
		 * 0: disable irq.
@@ -541,7 +539,7 @@ static int loongarch_eiointc_writel(struct kvm_vcpu *vcpu,
		data = ~s->enable.reg_u32[index] & old_data & s->isr.reg_u32[index];
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index, mask, 0);
			eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 0);
		}
		break;
	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
@@ -615,10 +613,9 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
		 * update irq when isr is set.
		 */
		data = s->enable.reg_u64[index] & ~old_data & s->isr.reg_u64[index];
		index = index << 3;
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index + i, mask, 1);
			eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 1);
		}
		/*
		 * 0: disable irq.
@@ -627,7 +624,7 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
		data = ~s->enable.reg_u64[index] & old_data & s->isr.reg_u64[index];
		for (i = 0; i < sizeof(data); i++) {
			u8 mask = (data >> (i * 8)) & 0xff;
			eiointc_enable_irq(vcpu, s, index, mask, 0);
			eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 0);
		}
		break;
	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END: