* [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