1010#include <linux/bitops.h>
1111#include <linux/errno.h>
1212#include <linux/err.h>
13+ #include <linux/nospec.h>
1314#include <linux/uaccess.h>
1415#include <linux/kvm_host.h>
1516#include <asm/cacheflush.h>
@@ -127,6 +128,7 @@ static int kvm_riscv_vcpu_isa_check_host(unsigned long kvm_ext, unsigned long *g
127128 kvm_ext >= ARRAY_SIZE (kvm_isa_ext_arr ))
128129 return - ENOENT ;
129130
131+ kvm_ext = array_index_nospec (kvm_ext , ARRAY_SIZE (kvm_isa_ext_arr ));
130132 * guest_ext = kvm_isa_ext_arr [kvm_ext ];
131133 switch (* guest_ext ) {
132134 case RISCV_ISA_EXT_SMNPM :
@@ -443,13 +445,16 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu,
443445 unsigned long reg_num = reg -> id & ~(KVM_REG_ARCH_MASK |
444446 KVM_REG_SIZE_MASK |
445447 KVM_REG_RISCV_CORE );
448+ unsigned long regs_max = sizeof (struct kvm_riscv_core ) / sizeof (unsigned long );
446449 unsigned long reg_val ;
447450
448451 if (KVM_REG_SIZE (reg -> id ) != sizeof (unsigned long ))
449452 return - EINVAL ;
450- if (reg_num >= sizeof ( struct kvm_riscv_core ) / sizeof ( unsigned long ) )
453+ if (reg_num >= regs_max )
451454 return - ENOENT ;
452455
456+ reg_num = array_index_nospec (reg_num , regs_max );
457+
453458 if (reg_num == KVM_REG_RISCV_CORE_REG (regs .pc ))
454459 reg_val = cntx -> sepc ;
455460 else if (KVM_REG_RISCV_CORE_REG (regs .pc ) < reg_num &&
@@ -476,13 +481,16 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
476481 unsigned long reg_num = reg -> id & ~(KVM_REG_ARCH_MASK |
477482 KVM_REG_SIZE_MASK |
478483 KVM_REG_RISCV_CORE );
484+ unsigned long regs_max = sizeof (struct kvm_riscv_core ) / sizeof (unsigned long );
479485 unsigned long reg_val ;
480486
481487 if (KVM_REG_SIZE (reg -> id ) != sizeof (unsigned long ))
482488 return - EINVAL ;
483- if (reg_num >= sizeof ( struct kvm_riscv_core ) / sizeof ( unsigned long ) )
489+ if (reg_num >= regs_max )
484490 return - ENOENT ;
485491
492+ reg_num = array_index_nospec (reg_num , regs_max );
493+
486494 if (copy_from_user (& reg_val , uaddr , KVM_REG_SIZE (reg -> id )))
487495 return - EFAULT ;
488496
@@ -507,10 +515,13 @@ static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
507515 unsigned long * out_val )
508516{
509517 struct kvm_vcpu_csr * csr = & vcpu -> arch .guest_csr ;
518+ unsigned long regs_max = sizeof (struct kvm_riscv_csr ) / sizeof (unsigned long );
510519
511- if (reg_num >= sizeof ( struct kvm_riscv_csr ) / sizeof ( unsigned long ) )
520+ if (reg_num >= regs_max )
512521 return - ENOENT ;
513522
523+ reg_num = array_index_nospec (reg_num , regs_max );
524+
514525 if (reg_num == KVM_REG_RISCV_CSR_REG (sip )) {
515526 kvm_riscv_vcpu_flush_interrupts (vcpu );
516527 * out_val = (csr -> hvip >> VSIP_TO_HVIP_SHIFT ) & VSIP_VALID_MASK ;
@@ -526,10 +537,13 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
526537 unsigned long reg_val )
527538{
528539 struct kvm_vcpu_csr * csr = & vcpu -> arch .guest_csr ;
540+ unsigned long regs_max = sizeof (struct kvm_riscv_csr ) / sizeof (unsigned long );
529541
530- if (reg_num >= sizeof ( struct kvm_riscv_csr ) / sizeof ( unsigned long ) )
542+ if (reg_num >= regs_max )
531543 return - ENOENT ;
532544
545+ reg_num = array_index_nospec (reg_num , regs_max );
546+
533547 if (reg_num == KVM_REG_RISCV_CSR_REG (sip )) {
534548 reg_val &= VSIP_VALID_MASK ;
535549 reg_val <<= VSIP_TO_HVIP_SHIFT ;
@@ -548,11 +562,14 @@ static inline int kvm_riscv_vcpu_smstateen_set_csr(struct kvm_vcpu *vcpu,
548562 unsigned long reg_val )
549563{
550564 struct kvm_vcpu_smstateen_csr * csr = & vcpu -> arch .smstateen_csr ;
565+ unsigned long regs_max = sizeof (struct kvm_riscv_smstateen_csr ) /
566+ sizeof (unsigned long );
551567
552- if (reg_num >= sizeof (struct kvm_riscv_smstateen_csr ) /
553- sizeof (unsigned long ))
568+ if (reg_num >= regs_max )
554569 return - EINVAL ;
555570
571+ reg_num = array_index_nospec (reg_num , regs_max );
572+
556573 ((unsigned long * )csr )[reg_num ] = reg_val ;
557574 return 0 ;
558575}
@@ -562,11 +579,14 @@ static int kvm_riscv_vcpu_smstateen_get_csr(struct kvm_vcpu *vcpu,
562579 unsigned long * out_val )
563580{
564581 struct kvm_vcpu_smstateen_csr * csr = & vcpu -> arch .smstateen_csr ;
582+ unsigned long regs_max = sizeof (struct kvm_riscv_smstateen_csr ) /
583+ sizeof (unsigned long );
565584
566- if (reg_num >= sizeof (struct kvm_riscv_smstateen_csr ) /
567- sizeof (unsigned long ))
585+ if (reg_num >= regs_max )
568586 return - EINVAL ;
569587
588+ reg_num = array_index_nospec (reg_num , regs_max );
589+
570590 * out_val = ((unsigned long * )csr )[reg_num ];
571591 return 0 ;
572592}
0 commit comments