From: sashiko-bot@kernel.org
To: "Andy Chiu" <tchiu@tenstorrent.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH v1 2/2] RISC-V: KVM: fix vcpu vector context handling for kernel-mode vector
Date: Sat, 11 Jul 2026 02:22:42 +0000 [thread overview]
Message-ID: <20260711022242.A4DC61F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260711015835.767259-3-tchiu@tenstorrent.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Softirqs preempting `vcpu_load()` or `vcpu_put()` can call `kernel_vector_begin()` and catastrophically corrupt both host user and guest vector states.
- [High] Missing `rcu_read_lock()` in `__riscv_flush_vector_context()` causes a lockdep warning and a Use-After-Free on PREEMPT_RT kernels during KVM module unload.
- [High] Missing bitmask when checking guest `sstatus.VS` field unconditionally forces vector enablement in the guest OS.
- [High] A preemption window allows guest vector state to overwrite the host userspace vector state buffer.
--
--- Patch [2]: [PATCH v1 2/2] RISC-V: KVM: fix vcpu vector context handling for kernel-mode vector ---
commit 1f94d99a9de1c321461c33680cf69b26f4efb606
Author: Andy Chiu <tchiu@tenstorrent.com>
Subject: RISC-V: KVM: fix vcpu vector context handling for kernel-mode vector
This patch registers an RCU-protected callback to allow the kernel-mode
vector code to safely flush the KVM guest's vector context. This addresses a
reverse dependency issue when KVM is configured as a module.
Fixes: ecd2ada8a5e0 ("riscv: Add support for kernel mode vector")
> diff --git a/arch/riscv/kernel/kernel_mode_vector.c b/arch/riscv/kernel/kernel_mode_vector.c
> index 307ac369c3d4a..a83d5c26d3b2c 100644
> --- a/arch/riscv/kernel/kernel_mode_vector.c
> +++ b/arch/riscv/kernel/kernel_mode_vector.c
[ ... ]
> @@ -80,6 +99,19 @@ void put_cpu_vector_context(void)
> preempt_enable();
> }
>
> +static void __riscv_flush_vector_context(void)
> +{
> + bool (*vcpu_flush_v_callback)(void);
> +
> + /* rcu_deference is protected by get/put_cpu_vector_context() */
> + vcpu_flush_v_callback = rcu_dereference(kvm_flush_vector_ctx_callback);
[Severity: High]
Does this missing rcu_read_lock() trigger a lockdep warning and risk a
use-after-free on PREEMPT_RT?
The caller get_cpu_vector_context() disables softirqs (or preemption on
RT), which does not constitute an RCU read-side critical section.
Furthermore, on PREEMPT_RT, preempt_disable() does not block
synchronize_rcu(). Could kvm_riscv_unregister_vctx_callback() return while
the callback is still executing and prematurely free the memory?
> + if (vcpu_flush_v_callback && vcpu_flush_v_callback())
> + return;
> +
> + riscv_v_vstate_save(¤t->thread.vstate, task_pt_regs(current));
> + riscv_v_vstate_set_restore(current, task_pt_regs(current));
> +}
[ ... ]
> @@ -141,13 +173,10 @@ static int riscv_v_start_kernel_context(void)
> }
>
> /* Transfer the ownership of V from user to kernel, then save */
> - riscv_v_start(RISCV_PREEMPT_V | RISCV_PREEMPT_V_DIRTY);
> - if (__riscv_v_vstate_check(task_pt_regs(current)->status, DIRTY)) {
> - uvstate = ¤t->thread.vstate;
> - __riscv_v_vstate_save(uvstate, uvstate->datap);
> - }
> - riscv_preempt_v_clear_dirty(current);
> - riscv_v_vstate_set_restore(current, task_pt_regs(current));
> + get_cpu_vector_context();
> + __riscv_flush_vector_context();
> + put_cpu_vector_context();
> + riscv_v_start(RISCV_PREEMPT_V);
[Severity: High]
Does the gap between put_cpu_vector_context() and riscv_v_start() create
a preemption window that allows guest state to overwrite host user state?
Calling put_cpu_vector_context() enables preemption and bottom halves. If a
context switch occurs exactly here, switch_to() calls __switch_to_vector(),
which observes that riscv_preempt_v_started(prev) is false.
Since the host's status was not cleared of SR_VS_DIRTY, __switch_to_vector()
might save the physical vector registers (which contain guest state) into
the host QEMU process's prev->thread.vstate.
> return 0;
> }
>
[ ... ]
> diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
> index cf6e231e76e25..60288bf6e9be4 100644
> --- a/arch/riscv/kvm/vcpu.c
> +++ b/arch/riscv/kvm/vcpu.c
[ ... ]
> @@ -765,6 +765,12 @@ static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu,
> kvm_riscv_vcpu_swap_in_guest_state(vcpu);
> guest_state_enter_irqoff();
>
> + if (current->thread.riscv_v_flags & RISCV_V_VCPU_NEED_RESTORE) {
> + current->thread.riscv_v_flags &= ~RISCV_V_VCPU_NEED_RESTORE;
> + __kvm_riscv_vector_restore(gcntx);
> + gcntx->sstatus = (gcntx->sstatus & ~SR_VS) | SR_VS_CLEAN;
> + }
> +
[Severity: High]
Could this forcefully overwrite the guest's sstatus register based on a false
positive in kvm_riscv_vcpu_flush_vector(), breaking guest OS lazy vector
state?
> if (kvm_riscv_nacl_sync_sret_available()) {
> nsh = nacl_shmem();
[ ... ]
> diff --git a/arch/riscv/kvm/vcpu_vector.c b/arch/riscv/kvm/vcpu_vector.c
> index 62d2fb77bb9b9..3b94e6e7fec84 100644
> --- a/arch/riscv/kvm/vcpu_vector.c
> +++ b/arch/riscv/kvm/vcpu_vector.c
[ ... ]
> @@ -95,6 +95,24 @@ void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu)
> kfree(vcpu->arch.guest_context.vector.datap);
> kfree(vcpu->arch.host_context.vector.datap);
> }
> +
> +bool kvm_riscv_vcpu_flush_vector(void)
> +{
> + struct kvm_vcpu *vcpu;
> +
> + vcpu = *this_cpu_ptr(kvm_get_running_vcpus());
[Severity: High]
Can a softirq occurring during vcpu_load() or vcpu_put() mistakenly use this
guest context?
In virt/kvm/kvm_main.c, vcpu_load() assigns the kvm_running_vcpu per-cpu
variable while preemption is disabled via get_cpu(), but hardware interrupts
can still occur. On return from a hardirq, invoke_softirq() could run.
If a softirq executes kernel_vector_begin(), it would find a non-NULL
kvm_running_vcpu here and wrongly assume the physical registers hold guest
state. This could result in saving the host userspace vector state into
guest_context, causing an information leak, and later clobbering the host
context in kvm_arch_vcpu_load().
> + if (vcpu && riscv_isa_extension_available(vcpu->arch.isa, v)) {
> + kvm_riscv_vcpu_guest_vector_save(&vcpu->arch.guest_context,
> + vcpu->arch.isa);
> +
> + if (vcpu->arch.guest_context.sstatus != SR_VS_OFF)
[Severity: High]
Does this comparison unconditionally evaluate to true because it is missing a
bitwise AND mask?
Because sstatus usually contains other active flags (like SR_SPP), comparing
the entire 64-bit register against SR_VS_OFF (which is 0) will almost always
evaluate to true.
Could this use (vcpu->arch.guest_context.sstatus & SR_VS) != SR_VS_OFF
instead?
> + current->thread.riscv_v_flags |= RISCV_V_VCPU_NEED_RESTORE;
> +
> + return true;
> + }
> + return false;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260711015835.767259-1-tchiu@tenstorrent.com?part=2
prev parent reply other threads:[~2026-07-11 2:22 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260711015835.767259-1-tchiu@tenstorrent.com>
2026-07-11 1:58 ` [PATCH v1 2/2] RISC-V: KVM: fix vcpu vector context handling for kernel-mode vector Andy Chiu
2026-07-11 2:22 ` 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=20260711022242.A4DC61F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tchiu@tenstorrent.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox