]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: riscv: Fix Spectre-v1 in vector register access
authorZongmin Zhou <zhouzongmin@kylinos.cn>
Wed, 15 Jul 2026 03:08:18 +0000 (11:08 +0800)
committerAnup Patel <anup@brainfault.org>
Wed, 15 Jul 2026 12:36:16 +0000 (18:06 +0530)
User-controlled register indices from the ONE_REG ioctl are used to
index into the vector register buffer (v0..v31). Sanitize the calculated
offset with array_index_nospec() to prevent speculative out-of-bounds
access.

Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260715030818.75657-1-min_halo@163.com
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/kvm/vcpu_vector.c

index 62d2fb77bb9b931681d5901e37befd974a271fbc..3708616e2c327e5b4fbf8d8a5c8d155629a2d4aa 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
+#include <linux/nospec.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
 #include <asm/kvm_isa.h>
@@ -129,11 +130,20 @@ static int kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu,
                        return -ENOENT;
                }
        } else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) {
+               unsigned long reg_offset;
+
                if (reg_size != vlenb)
                        return -EINVAL;
                WARN_ON(!cntx->vector.datap);
-               *reg_addr = cntx->vector.datap +
-                           (reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb;
+               /*
+                * The reg_num is derived from the userspace-provided ONE_REG
+                * id. Sanitize it with array_index_nospec() to prevent
+                * speculative out-of-bounds access to the vector register
+                * buffer (32 vector registers: v0..v31).
+                */
+               reg_offset = array_index_nospec(
+                               reg_num - KVM_REG_RISCV_VECTOR_REG(0), 32);
+               *reg_addr = cntx->vector.datap + reg_offset * vlenb;
        } else {
                return -ENOENT;
        }