Skip to content

Commit 8f0c15c

Browse files
Lukas Gerlachavpatel
authored andcommitted
KVM: riscv: Fix Spectre-v1 in floating-point register access
User-controlled indices are used to index into floating-point registers. Sanitize them with array_index_nospec() to prevent speculative out-of-bounds access. Reviewed-by: Radim Krčmář <radim.krcmar@oss.qualcomm.com> Signed-off-by: Lukas Gerlach <lukas.gerlach@cispa.de> Link: https://lore.kernel.org/r/20260303-kvm-riscv-spectre-v1-v2-3-192caab8e0dc@cispa.de Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent ec87a82 commit 8f0c15c

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

arch/riscv/kvm/vcpu_fp.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/errno.h>
1111
#include <linux/err.h>
1212
#include <linux/kvm_host.h>
13+
#include <linux/nospec.h>
1314
#include <linux/uaccess.h>
1415
#include <asm/cpufeature.h>
1516

@@ -93,9 +94,11 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
9394
if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr))
9495
reg_val = &cntx->fp.f.fcsr;
9596
else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) &&
96-
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
97+
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) {
98+
reg_num = array_index_nospec(reg_num,
99+
ARRAY_SIZE(cntx->fp.f.f));
97100
reg_val = &cntx->fp.f.f[reg_num];
98-
else
101+
} else
99102
return -ENOENT;
100103
} else if ((rtype == KVM_REG_RISCV_FP_D) &&
101104
riscv_isa_extension_available(vcpu->arch.isa, d)) {
@@ -107,6 +110,8 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
107110
reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) {
108111
if (KVM_REG_SIZE(reg->id) != sizeof(u64))
109112
return -EINVAL;
113+
reg_num = array_index_nospec(reg_num,
114+
ARRAY_SIZE(cntx->fp.d.f));
110115
reg_val = &cntx->fp.d.f[reg_num];
111116
} else
112117
return -ENOENT;
@@ -138,9 +143,11 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
138143
if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr))
139144
reg_val = &cntx->fp.f.fcsr;
140145
else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) &&
141-
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
146+
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) {
147+
reg_num = array_index_nospec(reg_num,
148+
ARRAY_SIZE(cntx->fp.f.f));
142149
reg_val = &cntx->fp.f.f[reg_num];
143-
else
150+
} else
144151
return -ENOENT;
145152
} else if ((rtype == KVM_REG_RISCV_FP_D) &&
146153
riscv_isa_extension_available(vcpu->arch.isa, d)) {
@@ -152,6 +159,8 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
152159
reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) {
153160
if (KVM_REG_SIZE(reg->id) != sizeof(u64))
154161
return -EINVAL;
162+
reg_num = array_index_nospec(reg_num,
163+
ARRAY_SIZE(cntx->fp.d.f));
155164
reg_val = &cntx->fp.d.f[reg_num];
156165
} else
157166
return -ENOENT;

0 commit comments

Comments
 (0)