All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Bibo Mao" <maobibo@loongson.cn>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH] LoongArch: KVM: User internal API to deliver interrupt in kernel mode
Date: Tue, 16 Jun 2026 08:57:02 +0000	[thread overview]
Message-ID: <20260616085702.CD0F91F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260616084538.2274484-1-maobibo@loongson.cn>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [Critical] The KVM_INTERRUPT ioctl lacks bounds checking on the user-provided interrupt number, allowing unprivileged host userspace to trigger out-of-bounds bit operations.
- [Critical] Guest-controlled interrupt pin number extraction allows out-of-bounds bitwise writes in host kernel memory.
- [High] Time-of-check to time-of-use (TOCTOU) race condition in IPI delivery and clearance allows inter-processor interrupts to be lost.
--

commit 29e0cf4460ddc2a662b4de4e3946b4ad4d5ce123
Author: Bibo Mao <maobibo@loongson.cn>

LoongArch: KVM: User internal API to deliver interrupt in kernel mode

This commit refactors interrupt delivery in kernel mode to use the internal
APIs kvm_queue_irq() and kvm_dequeue_irq() directly, bypassing the ioctl
interface. It also removes the printk error message for invalid interrupts
with number 0.

> diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
> index 2ab7fafa86d59..63f917de7903c 100644
> --- a/arch/loongarch/kvm/intc/eiointc.c
> +++ b/arch/loongarch/kvm/intc/eiointc.c
[ ... ]
> @@ -67,8 +66,11 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
>  	if (found < EIOINTC_IRQS)
>  		return; /* other irq is handling, needn't update parent irq */
>  
> -	vcpu_irq.irq = level ? (INT_HWI0 + ipnum) : -(INT_HWI0 + ipnum);
> -	kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq);
> +	if (level)
> +		kvm_queue_irq(vcpu, INT_HWI0 + ipnum);

[Severity: Critical]
This isn't a bug introduced by this patch, but does the guest-controlled
ipnum lack bounds checking before being used here?

In eiointc_update_irq(), ipnum is calculated from the guest-controlled
s->ipmap register. If the guest enables EIOINTC_ENABLE_INT_ENCODE, this
value can be passed unmodified.

Since INT_HWI0 is 2, the passed IRQ number can be up to 257. Because
kvm_queue_irq() uses this to set a bit in vcpu->arch.irq_pending (which
is a single 64-bit unsigned long), does this write past the end of
irq_pending and corrupt adjacent host memory?

> +	else
> +		kvm_dequeue_irq(vcpu, INT_HWI0 + ipnum);
> +	kvm_vcpu_kick(vcpu);
>  }

> diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c
> index 1f6ebbd0af5c8..ab3d894eb1469 100644
> --- a/arch/loongarch/kvm/intc/ipi.c
> +++ b/arch/loongarch/kvm/intc/ipi.c
[ ... ]
> @@ -10,15 +10,14 @@
>  static void ipi_set(struct kvm_vcpu *vcpu, uint32_t data)
>  {
>  	uint32_t status;
> -	struct kvm_interrupt irq;
>  
>  	spin_lock(&vcpu->arch.ipi_state.lock);
>  	status = vcpu->arch.ipi_state.status;
>  	vcpu->arch.ipi_state.status |= data;
>  	spin_unlock(&vcpu->arch.ipi_state.lock);
>  	if ((status == 0) && data) {
> -		irq.irq = LARCH_INT_IPI;
> -		kvm_vcpu_ioctl_interrupt(vcpu, &irq);
> +		kvm_queue_irq(vcpu, LARCH_INT_IPI);

[Severity: High]
This isn't a bug introduced by this patch, but can a race condition here
cause inter-processor interrupts to be lost?

The queuing of the interrupt via kvm_queue_irq() happens outside the lock
based on a local snapshot of status. If CPU 0 clears an IPI and unlocks, and
CPU 1 sets a new IPI and queues it, could CPU 0 then resume and incorrectly
execute kvm_dequeue_irq() based on its stale status?

> +		kvm_vcpu_kick(vcpu);
>  	}
>  }
>  
[ ... ]
> @@ -40,15 +39,14 @@ static void ipi_send(struct kvm *kvm, uint64_t data)
>  static void ipi_clear(struct kvm_vcpu *vcpu, uint64_t data)
>  {
>  	uint32_t status;
> -	struct kvm_interrupt irq;
>  
>  	spin_lock(&vcpu->arch.ipi_state.lock);
>  	vcpu->arch.ipi_state.status &= ~data;
>  	status = vcpu->arch.ipi_state.status;
>  	spin_unlock(&vcpu->arch.ipi_state.lock);
>  	if (status == 0) {
> -		irq.irq = -LARCH_INT_IPI;
> -		kvm_vcpu_ioctl_interrupt(vcpu, &irq);
> +		kvm_dequeue_irq(vcpu, LARCH_INT_IPI);

[Severity: High]
This isn't a bug introduced by this patch, but this dequeue operation appears
to mirror the race condition mentioned above, potentially clearing an interrupt
that was just queued by another CPU.

> +		kvm_vcpu_kick(vcpu);
>  	}
>  }

> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index e28084c49e682..bd90be3f498b4 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
[ ... ]
> @@ -1492,10 +1492,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
>  		kvm_queue_irq(vcpu, intr);
>  	else if (intr < 0)
>  		kvm_dequeue_irq(vcpu, -intr);

[Severity: Critical]
This isn't a bug introduced by this patch, but does the KVM_INTERRUPT ioctl
handler lack bounds checking on the user-provided interrupt number?

The ioctl parses an __u32 irq from user memory and passes it to
kvm_vcpu_ioctl_interrupt(), which unconditionally passes it to
kvm_queue_irq() or kvm_dequeue_irq().

Since these functions execute atomic bit operations (set_bit/clear_bit) on
vcpu->arch.irq_pending and vcpu->arch.irq_clear (which are single 64-bit
unsigned long values), could an unprivileged host process with /dev/kvm
access supply arbitrarily large values to manipulate host kernel memory
outside the bounds of the VCPU architecture struct?

> -	else {
> -		kvm_err("%s: invalid interrupt ioctl %d\n", __func__, irq->irq);
> +	else
>  		return -EINVAL;
> -	}
>  
>  	kvm_vcpu_kick(vcpu);
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616084538.2274484-1-maobibo@loongson.cn?part=1

      reply	other threads:[~2026-06-16  8:57 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-16  8:45 [PATCH] LoongArch: KVM: User internal API to deliver interrupt in kernel mode Bibo Mao
2026-06-16  8:57 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260616085702.CD0F91F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=maobibo@loongson.cn \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.