Currently, if we need to check the value of the register defined by user space, we should check it in set_user. However, some system registers may use the same set_user (for example, almost all ID registers), which make it difficult to validate the value defined by user space. Introduce check_user to solve the problem. And apply check_user before set_user to make sure that the value of register is valid. Signed-off-by: zhanghailiang <zhang.zhanghailiang@xxxxxxxxxx> Signed-off-by: Peng Liang <liangpeng10@xxxxxxxxxx> --- arch/arm64/kvm/sys_regs.c | 7 +++++++ arch/arm64/kvm/sys_regs.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2b0fa8d5ac62..86ebb8093c3c 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2684,6 +2684,7 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg { const struct sys_reg_desc *r; void __user *uaddr = (void __user *)(unsigned long)reg->addr; + int err; if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX) return demux_c15_set(reg->id, uaddr); @@ -2699,6 +2700,12 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg if (sysreg_hidden_from_user(vcpu, r)) return -ENOENT; + if (r->check_user) { + err = (r->check_user)(vcpu, r, reg, uaddr); + if (err) + return err; + } + if (r->set_user) return (r->set_user)(vcpu, r, reg, uaddr); diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index 5a6fc30f5989..9bce5e9a3490 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -53,6 +53,12 @@ struct sys_reg_desc { const struct kvm_one_reg *reg, void __user *uaddr); int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, const struct kvm_one_reg *reg, void __user *uaddr); + /* + * Check the value userspace passed. It should return 0 on success and + * otherwise on failure. + */ + int (*check_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr); /* Return mask of REG_* runtime visibility overrides */ unsigned int (*visibility)(const struct kvm_vcpu *vcpu, -- 2.26.2