Re: [RFCv2.1] KVM: S390: protvirt: Introduce instruction data area bounce buffer

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

 



>  #define CPUSTAT_STOPPED    0x80000000
>  #define CPUSTAT_WAIT       0x10000000
>  #define CPUSTAT_ECALL_PEND 0x08000000
> @@ -315,7 +321,10 @@ struct kvm_s390_sie_block {
>  #define CRYCB_FORMAT2 0x00000003
>  	__u32	crycbd;			/* 0x00fc */
>  	__u64	gcr[16];		/* 0x0100 */
> -	__u64	gbea;			/* 0x0180 */
> +	union {
> +		__u64	gbea;			/* 0x0180 */
> +		__u64	sidad;
> +	};
>  	__u8    reserved188[8];		/* 0x0188 */
>  	__u64   sdnxo;			/* 0x0190 */
>  	__u8    reserved198[8];		/* 0x0198 */
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 6f90d16cad92..56488f9ed190 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -4435,6 +4435,41 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
>  	return r;
>  }
>  
> +static long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu,
> +				   struct kvm_s390_mem_op *mop)
> +{
> +	void __user *uaddr = (void __user *)mop->buf;
> +	int r = 0;
> +
> +	if (mop->flags || !mop->size)
> +		return -EINVAL;
> +
> +	if (mop->size > sida_size(vcpu->arch.sie_block))
> +		return -E2BIG;
> +
> +	if (mop->sida_offset > sida_size(vcpu->arch.sie_block))
> +		return -E2BIG;
> +
> +	if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block))
> +		return -E2BIG;
> +

if (mop->size + mop->sida_offset > mop->size)
	return -EINVAL;
if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block))
	return -E2BIG;

Should be sufficient (instead of 3 checks).

> +	switch (mop->op) {
> +	case KVM_S390_MEMOP_SIDA_READ:
> +		r = 0;
> +		if (copy_to_user(uaddr, (void *)(sida_origin(vcpu->arch.sie_block) +
> +				 mop->sida_offset), mop->size))
> +			r = -EFAULT;
> +
> +		break;
> +	case KVM_S390_MEMOP_SIDA_WRITE:
> +		r = 0;
> +		if (copy_from_user((void *)(sida_origin(vcpu->arch.sie_block) +
> +				   mop->sida_offset), uaddr, mop->size))
> +			r = -EFAULT;
> +		break;
> +	}
> +	return r;
> +}
>  static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
>  				  struct kvm_s390_mem_op *mop)
>  {
> @@ -4444,6 +4479,8 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
>  	const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION
>  				    | KVM_S390_MEMOP_F_CHECK_ONLY;
>  
> +
> +	BUILD_BUG_ON(sizeof(*mop) != 64);
>  	if (mop->flags & ~supported_flags || mop->ar >= NUM_ACRS || !mop->size)
>  		return -EINVAL;
>  
> @@ -4460,6 +4497,10 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
>  
>  	switch (mop->op) {
>  	case KVM_S390_MEMOP_LOGICAL_READ:
> +		if (kvm_s390_pv_is_protected(vcpu->kvm)) {
> +			r = -EINVAL;
> +			break;
> +		}

Race with PV_VM_DESTROY (freeing sidad)

>  		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
>  			r = check_gva_range(vcpu, mop->gaddr, mop->ar,
>  					    mop->size, GACC_FETCH);
> @@ -4472,6 +4513,10 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
>  		}
>  		break;
>  	case KVM_S390_MEMOP_LOGICAL_WRITE:
> +		if (kvm_s390_pv_is_protected(vcpu->kvm)) {
> +			r = -EINVAL;
> +			break;
> +		}

Race with PV_VM_DESTROY (freeing sidad)


-- 
Thanks,

David / dhildenb




[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