Re: [RFC v2 4/7] kvm: arm64: introduce check_user

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 17, 2020 at 08:00:58PM +0800, Peng Liang wrote:
> 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.

If sharing set_user no longer makes sense for ID registers, then we need
to rework the code so it's no longer shared. As I keep saying, we need
to address this problem one ID register at a time. So, IMO, the approach
should be to change one ID register at a time from using ID_SANITISED()
to having its own table entry with its own set/get_user code. There may
still be opportunity to share code among the ID registers, in which case
refactoring can be done as needed too.

Thanks,
drew

> 
> 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
> 




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux