The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/2] LoongArch: KVM: EIOINTC: fix INT_ENCODE ipnum out-of-bounds access
@ 2026-07-14  1:24 Tao Cui
  2026-07-14  1:24 ` [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode Tao Cui
  2026-07-14  1:24 ` [PATCH 2/2] LoongArch: KVM: EIOINTC: factor IP-number decode into a helper Tao Cui
  0 siblings, 2 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-14  1:24 UTC (permalink / raw)
  To: zhaotianrui, maobibo, chenhuacai
  Cc: kernel, lixianglai, kvm, loongarch, linux-kernel, stable, Tao Cui

From: Tao Cui <cuitao@kylinos.cn>

This small series fixes a guest-triggerable out-of-bounds access in the
LoongArch KVM EIOINTC emulation, then factors the duplicated IP-number
decode into a helper.

The IP-number decode in eiointc_set_sw_coreisr() and eiointc_update_irq()
bounds ipnum only in the default (1-hot) mode. In INT_ENCODE mode the raw
ipmap byte (0..255) is used to index sw_coreisr[cpu][ipnum], whose second
dimension is LOONGSON_IP_NUM (8), so any ipmap byte >= 8 reads/writes past
the array. The value is guest-programmable through the EIOINTC virtual
extension (VIRT_CONFIG enables INT_ENCODE and the IPMAP IOCSR write is not
validated) and is also restored from a migration stream via the
LOAD_FINISHED control attribute, so this is a host slab out-of-bounds
access reachable from an unprivileged guest.

Patch 1 is the minimal, stable-bound fix: clamp ipnum to [0, LOONGSON_IP_NUM)
in INT_ENCODE mode at both call sites. Patch 2 is a follow-up cleanup that
extracts the now-identical decode into eiointc_get_ipnum() (no functional
change); it is split out so the fix stays surgical for backporting.

Verified with KASAN on Loongson-3A6000: the device-attr restore sequence
(INT_ENCODE + ipmap byte 0x80 + LOAD_FINISHED) reports
"BUG: KASAN: slab-out-of-bounds in eiointc_set_sw_coreisr" without the
series and is clean with it.

Patch 1 carries Fixes:/Cc: stable; patch 2 is mainline-only.

Tao Cui (2):
  LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode
  LoongArch: KVM: EIOINTC: factor IP-number decode into a helper

 arch/loongarch/kvm/intc/eiointc.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

--
2.43.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode
  2026-07-14  1:24 [PATCH 0/2] LoongArch: KVM: EIOINTC: fix INT_ENCODE ipnum out-of-bounds access Tao Cui
@ 2026-07-14  1:24 ` Tao Cui
  2026-07-14  2:32   ` Bibo Mao
  2026-07-14  1:24 ` [PATCH 2/2] LoongArch: KVM: EIOINTC: factor IP-number decode into a helper Tao Cui
  1 sibling, 1 reply; 5+ messages in thread
From: Tao Cui @ 2026-07-14  1:24 UTC (permalink / raw)
  To: zhaotianrui, maobibo, chenhuacai
  Cc: kernel, lixianglai, kvm, loongarch, linux-kernel, stable, Tao Cui

From: Tao Cui <cuitao@kylinos.cn>

The IP-number decode in eiointc_set_sw_coreisr() and eiointc_update_irq()
clamps ipnum only in the default (1-hot) mode. In INT_ENCODE mode the raw
ipmap byte (0..255) is used as the index into sw_coreisr[cpu][ipnum],
whose second dimension is LOONGSON_IP_NUM (8), so any ipmap byte >= 8
accesses the array out of bounds.

The value is guest-programmable through the EIOINTC virtual extension
(VIRT_CONFIG enables INT_ENCODE and the IPMAP IOCSR write is unvalidated)
and is also restored unvalidated from a migration stream via the
LOAD_FINISHED control attribute, resulting in a host slab out-of-bounds
access reachable from an unprivileged guest.

Clamp ipnum to [0, LOONGSON_IP_NUM) in INT_ENCODE mode as well.

Fixes: 3956a52bc05b ("LoongArch: KVM: Add EIOINTC read and write functions")
Cc: stable@vger.kernel.org
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
 arch/loongarch/kvm/intc/eiointc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
index 2b14485d14a7..0c34d7ab264d 100644
--- a/arch/loongarch/kvm/intc/eiointc.c
+++ b/arch/loongarch/kvm/intc/eiointc.c
@@ -17,6 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
 		if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
 			ipnum = count_trailing_zeros(ipnum);
 			ipnum = ipnum < 4 ? ipnum : 0;
+		} else {
+			ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
 		}
 
 		cpuid = ((u8 *)s->coremap)[irq];
@@ -42,6 +44,8 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
 	if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
 		ipnum = count_trailing_zeros(ipnum);
 		ipnum = ipnum < 4 ? ipnum : 0;
+	} else {
+		ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
 	}
 
 	cpu = s->sw_coremap[irq];
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] LoongArch: KVM: EIOINTC: factor IP-number decode into a helper
  2026-07-14  1:24 [PATCH 0/2] LoongArch: KVM: EIOINTC: fix INT_ENCODE ipnum out-of-bounds access Tao Cui
  2026-07-14  1:24 ` [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode Tao Cui
@ 2026-07-14  1:24 ` Tao Cui
  1 sibling, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-14  1:24 UTC (permalink / raw)
  To: zhaotianrui, maobibo, chenhuacai
  Cc: kernel, lixianglai, kvm, loongarch, linux-kernel, stable, Tao Cui

From: Tao Cui <cuitao@kylinos.cn>

The ipmap IP-number decode is duplicated in eiointc_set_sw_coreisr() and
eiointc_update_irq(). Factor it into eiointc_get_ipnum().

No functional change.

Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
 arch/loongarch/kvm/intc/eiointc.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
index 0c34d7ab264d..c1e0cd8dca16 100644
--- a/arch/loongarch/kvm/intc/eiointc.c
+++ b/arch/loongarch/kvm/intc/eiointc.c
@@ -7,19 +7,27 @@
 #include <asm/kvm_vcpu.h>
 #include <linux/count_zeros.h>
 
+static int eiointc_get_ipnum(struct loongarch_eiointc *s, int irq)
+{
+	int ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
+
+	if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
+		ipnum = count_trailing_zeros(ipnum);
+		ipnum = ipnum < 4 ? ipnum : 0;
+	} else {
+		ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
+	}
+
+	return ipnum;
+}
+
 static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
 {
 	int ipnum, cpu, cpuid, irq;
 	struct kvm_vcpu *vcpu;
 
 	for (irq = 0; irq < EIOINTC_IRQS; irq++) {
-		ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
-		if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
-			ipnum = count_trailing_zeros(ipnum);
-			ipnum = ipnum < 4 ? ipnum : 0;
-		} else {
-			ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
-		}
+		ipnum = eiointc_get_ipnum(s, irq);
 
 		cpuid = ((u8 *)s->coremap)[irq];
 		vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid);
@@ -40,13 +48,7 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
 	struct kvm_vcpu *vcpu;
 	struct kvm_interrupt vcpu_irq;
 
-	ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
-	if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
-		ipnum = count_trailing_zeros(ipnum);
-		ipnum = ipnum < 4 ? ipnum : 0;
-	} else {
-		ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
-	}
+	ipnum = eiointc_get_ipnum(s, irq);
 
 	cpu = s->sw_coremap[irq];
 	vcpu = kvm_get_vcpu_by_id(s->kvm, cpu);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode
  2026-07-14  1:24 ` [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode Tao Cui
@ 2026-07-14  2:32   ` Bibo Mao
  2026-07-14  3:19     ` Tao Cui
  0 siblings, 1 reply; 5+ messages in thread
From: Bibo Mao @ 2026-07-14  2:32 UTC (permalink / raw)
  To: Tao Cui, zhaotianrui, chenhuacai
  Cc: kernel, lixianglai, kvm, loongarch, linux-kernel, stable, Tao Cui

Hi Tao,

Thanks to catch this, there is similar modification which can be located at:
https://lore.kernel.org/lkml/20260709082109.1361767-5-maobibo@loongson.cn/

Regards
Bibo Mao

On 2026/7/14 上午9:24, Tao Cui wrote:
> From: Tao Cui <cuitao@kylinos.cn>
> 
> The IP-number decode in eiointc_set_sw_coreisr() and eiointc_update_irq()
> clamps ipnum only in the default (1-hot) mode. In INT_ENCODE mode the raw
> ipmap byte (0..255) is used as the index into sw_coreisr[cpu][ipnum],
> whose second dimension is LOONGSON_IP_NUM (8), so any ipmap byte >= 8
> accesses the array out of bounds.
> 
> The value is guest-programmable through the EIOINTC virtual extension
> (VIRT_CONFIG enables INT_ENCODE and the IPMAP IOCSR write is unvalidated)
> and is also restored unvalidated from a migration stream via the
> LOAD_FINISHED control attribute, resulting in a host slab out-of-bounds
> access reachable from an unprivileged guest.
> 
> Clamp ipnum to [0, LOONGSON_IP_NUM) in INT_ENCODE mode as well.
> 
> Fixes: 3956a52bc05b ("LoongArch: KVM: Add EIOINTC read and write functions")
> Cc: stable@vger.kernel.org
> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
> ---
>   arch/loongarch/kvm/intc/eiointc.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 
> diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
> index 2b14485d14a7..0c34d7ab264d 100644
> --- a/arch/loongarch/kvm/intc/eiointc.c
> +++ b/arch/loongarch/kvm/intc/eiointc.c
> @@ -17,6 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
>   		if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
>   			ipnum = count_trailing_zeros(ipnum);
>   			ipnum = ipnum < 4 ? ipnum : 0;
> +		} else {
> +			ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
>   		}
>   
>   		cpuid = ((u8 *)s->coremap)[irq];
> @@ -42,6 +44,8 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
>   	if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
>   		ipnum = count_trailing_zeros(ipnum);
>   		ipnum = ipnum < 4 ? ipnum : 0;
> +	} else {
> +		ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
>   	}
>   
>   	cpu = s->sw_coremap[irq];
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode
  2026-07-14  2:32   ` Bibo Mao
@ 2026-07-14  3:19     ` Tao Cui
  0 siblings, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-14  3:19 UTC (permalink / raw)
  To: Bibo Mao, zhaotianrui, chenhuacai
  Cc: cui.tao, kernel, lixianglai, kvm, loongarch, linux-kernel, stable,
	Tao Cui



在 2026/7/14 10:32, Bibo Mao 写道:
> Hi Tao,
> 
> Thanks to catch this, there is similar modification which can be located at:
> https://lore.kernel.org/lkml/20260709082109.1361767-5-maobibo@loongson.cn/
> 
Hi Bibo,

Haha, looks like we raced to the same fix :) I came across it while
debugging VM migration (the LOAD_FINISHED restore path). Your patch
takes priority — I'll go ahead and drop my series.

Thanks,
Tao

> Regards
> Bibo Mao
> 
> On 2026/7/14 上午9:24, Tao Cui wrote:
>> From: Tao Cui <cuitao@kylinos.cn>
>>
>> The IP-number decode in eiointc_set_sw_coreisr() and eiointc_update_irq()
>> clamps ipnum only in the default (1-hot) mode. In INT_ENCODE mode the raw
>> ipmap byte (0..255) is used as the index into sw_coreisr[cpu][ipnum],
>> whose second dimension is LOONGSON_IP_NUM (8), so any ipmap byte >= 8
>> accesses the array out of bounds.
>>
>> The value is guest-programmable through the EIOINTC virtual extension
>> (VIRT_CONFIG enables INT_ENCODE and the IPMAP IOCSR write is unvalidated)
>> and is also restored unvalidated from a migration stream via the
>> LOAD_FINISHED control attribute, resulting in a host slab out-of-bounds
>> access reachable from an unprivileged guest.
>>
>> Clamp ipnum to [0, LOONGSON_IP_NUM) in INT_ENCODE mode as well.
>>
>> Fixes: 3956a52bc05b ("LoongArch: KVM: Add EIOINTC read and write functions")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
>> ---
>>   arch/loongarch/kvm/intc/eiointc.c | 4 ++++
>>   1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
>> index 2b14485d14a7..0c34d7ab264d 100644
>> --- a/arch/loongarch/kvm/intc/eiointc.c
>> +++ b/arch/loongarch/kvm/intc/eiointc.c
>> @@ -17,6 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
>>           if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
>>               ipnum = count_trailing_zeros(ipnum);
>>               ipnum = ipnum < 4 ? ipnum : 0;
>> +        } else {
>> +            ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
>>           }
>>             cpuid = ((u8 *)s->coremap)[irq];
>> @@ -42,6 +44,8 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
>>       if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
>>           ipnum = count_trailing_zeros(ipnum);
>>           ipnum = ipnum < 4 ? ipnum : 0;
>> +    } else {
>> +        ipnum = (ipnum < LOONGSON_IP_NUM) ? ipnum : 0;
>>       }
>>         cpu = s->sw_coremap[irq];
>>
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-14  3:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14  1:24 [PATCH 0/2] LoongArch: KVM: EIOINTC: fix INT_ENCODE ipnum out-of-bounds access Tao Cui
2026-07-14  1:24 ` [PATCH 1/2] LoongArch: KVM: EIOINTC: clamp ipnum to valid range in INT_ENCODE mode Tao Cui
2026-07-14  2:32   ` Bibo Mao
2026-07-14  3:19     ` Tao Cui
2026-07-14  1:24 ` [PATCH 2/2] LoongArch: KVM: EIOINTC: factor IP-number decode into a helper Tao Cui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox