Re: [PATCH v2] RISC-V: KVM: Fix use-after-free in kvm_riscv_gstage_get_leaf()
From: Anup Patel
Date: Thu Apr 02 2026 - 02:17:06 EST
On Wed, Apr 1, 2026 at 4:19 PM Jiakai Xu <xujiakai2025@xxxxxxxxxxx> wrote:
>
> Hi Anup,
>
> I've been fuzzing the latest kvm-riscv with the spin_trylock() fix
> applied, and I can still reproduce the use-after-free bug in
> kvm_riscv_gstage_get_leaf(). This indicates the current fix is
> insufficient.
>
> The current code does:
> mmu_locked = spin_trylock(&kvm->mmu_lock);
> kvm_riscv_gstage_unmap_range(...);
> if (mmu_locked)
> spin_unlock(&kvm->mmu_lock);
> When spin_trylock() fails (lock held by another CPU), the code still
> proceeds to access the gstage page table without any protection,
> leading to UAF when concurrent with kvm_riscv_mmu_free_pgd().
>
> The fundamental issue is that spin_trylock() returns false in two
> different cases:
> 1. Lock held by current thread (we should continue)
> 2. Lock held by another thread (we should NOT continue)
> But the current code doesn't distinguish between them.
>
> My proposed fix:
> Use lock_is_held_type() to check if current thread already holds the
> lock:
> bool need_unlock = false;
> if (!lock_is_held_type(&kvm->mmu_lock, LOCK_STATE_HELD)) {
> spin_lock(&kvm->mmu_lock);
> need_unlock = true;
> }
> kvm_riscv_gstage_unmap_range(...);
> if (need_unlock)
> spin_unlock(&kvm->mmu_lock);
>
> However, I'm not sure if this is the best approach. What do you think?
>
I don't mind improving this further but this now deserves some
comments about why we are doing this contional locking.
Regards,
Anup