LoongArch: KVM: Avoid overflow with array index
authorBibo Mao <maobibo@loongson.cn>
Thu, 26 Jun 2025 12:07:27 +0000 (20:07 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 26 Jun 2025 12:07:27 +0000 (20:07 +0800)
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: 3956a52bc05b ("LoongArch: KVM: Add EIOINTC read and write functions")
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/kvm/intc/eiointc.c

index f39929d7bf8a249587fb099bb1bbd0b65098f050..9c47456b805c9e6157e68649d00b3f558854499b 100644 (file)
@@ -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: