public inbox for linux-s390@vger.kernel.org
 help / color / mirror / Atom feed
From: Claudio Imbrenda <imbrenda@linux.ibm.com>
To: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Janis Schoetterl-Glausch <scgl@linux.ibm.com>,
	Heiko Carstens <hca@linux.ibm.com>,
	Janosch Frank <frankja@linux.ibm.com>,
	Alexander Gordeev <agordeev@linux.ibm.com>,
	David Hildenbrand <david@redhat.com>,
	Jonathan Corbet <corbet@lwn.net>,
	kvm@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org,
	Paolo Bonzini <pbonzini@redhat.com>,
	Sven Schnelle <svens@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>
Subject: Re: [PATCH v3 06/10] KVM: s390: Add vm IOCTL for key checked guest absolute memory access
Date: Thu, 10 Feb 2022 17:25:55 +0100	[thread overview]
Message-ID: <20220210172555.43141947@p-imbrenda> (raw)
In-Reply-To: <023fcd5d-4ee5-ad0e-ae7d-53b181e31a4e@linux.ibm.com>

On Thu, 10 Feb 2022 15:40:03 +0100
Christian Borntraeger <borntraeger@linux.ibm.com> wrote:

> Am 09.02.22 um 18:04 schrieb Janis Schoetterl-Glausch:
> > Channel I/O honors storage keys and is performed on absolute memory.
> > For I/O emulation user space therefore needs to be able to do key
> > checked accesses.
> > The vm IOCTL supports read/write accesses, as well as checking
> > if an access would succeed.
> > Unlike relying on KVM_S390_GET_SKEYS for key checking would,
> > the vm IOCTL performs the check in lockstep with the read or write,
> > by, ultimately, mapping the access to move instructions that
> > support key protection checking with a supplied key.
> > Fetch and storage protection override are not applicable to absolute
> > accesses and so are not applied as they are when using the vcpu memop.
> > 
> > Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
> > Acked-by: Janosch Frank <frankja@linux.ibm.com>  
> 
> same comment that you did for the vcpu part (default key)
> with that.
> 
> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>

I guess @linux.ibm.com ?

> > ---
> >   arch/s390/kvm/gaccess.c  | 72 ++++++++++++++++++++++++++++++++++++
> >   arch/s390/kvm/gaccess.h  |  6 +++
> >   arch/s390/kvm/kvm-s390.c | 79 ++++++++++++++++++++++++++++++++++++++++
> >   include/uapi/linux/kvm.h |  2 +
> >   4 files changed, 159 insertions(+)
> > 
> > diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
> > index 37838f637707..d53a183c2005 100644
> > --- a/arch/s390/kvm/gaccess.c
> > +++ b/arch/s390/kvm/gaccess.c
> > @@ -795,6 +795,35 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
> >   	return 1;
> >   }
> >   
> > +static int vm_check_access_key(struct kvm *kvm, u8 access_key,
> > +			       enum gacc_mode mode, gpa_t gpa)
> > +{
> > +	u8 storage_key, access_control;
> > +	bool fetch_protected;
> > +	unsigned long hva;
> > +	int r;
> > +
> > +	if (access_key == 0)
> > +		return 0;
> > +
> > +	hva = gfn_to_hva(kvm, gpa_to_gfn(gpa));
> > +	if (kvm_is_error_hva(hva))
> > +		return PGM_ADDRESSING;
> > +
> > +	mmap_read_lock(current->mm);
> > +	r = get_guest_storage_key(current->mm, hva, &storage_key);
> > +	mmap_read_unlock(current->mm);
> > +	if (r)
> > +		return r;
> > +	access_control = FIELD_GET(_PAGE_ACC_BITS, storage_key);
> > +	if (access_control == access_key)
> > +		return 0;
> > +	fetch_protected = storage_key & _PAGE_FP_BIT;
> > +	if ((mode == GACC_FETCH || mode == GACC_IFETCH) && !fetch_protected)
> > +		return 0;
> > +	return PGM_PROTECTION;
> > +}
> > +
> >   static bool fetch_prot_override_applicable(struct kvm_vcpu *vcpu, enum gacc_mode mode,
> >   					   union asce asce)
> >   {
> > @@ -994,6 +1023,26 @@ access_guest_page_with_key(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa,
> >   	return 0;
> >   }
> >   
> > +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,
> > +			      unsigned long len, enum gacc_mode mode, u8 access_key)
> > +{
> > +	int offset = offset_in_page(gpa);
> > +	int fragment_len;
> > +	int rc;
> > +
> > +	while (min(PAGE_SIZE - offset, len) > 0) {
> > +		fragment_len = min(PAGE_SIZE - offset, len);
> > +		rc = access_guest_page_with_key(kvm, mode, gpa, data, fragment_len, access_key);
> > +		if (rc)
> > +			return rc;
> > +		offset = 0;
> > +		len -= fragment_len;
> > +		data += fragment_len;
> > +		gpa += fragment_len;
> > +	}
> > +	return 0;
> > +}
> > +
> >   int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
> >   			  void *data, unsigned long len, enum gacc_mode mode,
> >   			  u8 access_key)
> > @@ -1144,6 +1193,29 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
> >   	return rc;
> >   }
> >   
> > +/**
> > + * check_gpa_range - test a range of guest physical addresses for accessibility
> > + * @kvm: virtual machine instance
> > + * @gpa: guest physical address
> > + * @length: length of test range
> > + * @mode: access mode to test, relevant for storage keys
> > + * @access_key: access key to mach the storage keys with
> > + */
> > +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,
> > +		    enum gacc_mode mode, u8 access_key)
> > +{
> > +	unsigned int fragment_len;
> > +	int rc = 0;
> > +
> > +	while (length && !rc) {
> > +		fragment_len = min(PAGE_SIZE - offset_in_page(gpa), length);
> > +		rc = vm_check_access_key(kvm, access_key, mode, gpa);
> > +		length -= fragment_len;
> > +		gpa += fragment_len;
> > +	}
> > +	return rc;
> > +}
> > +
> >   /**
> >    * kvm_s390_check_low_addr_prot_real - check for low-address protection
> >    * @vcpu: virtual cpu
> > diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
> > index c5f2e7311b17..1124ff282012 100644
> > --- a/arch/s390/kvm/gaccess.h
> > +++ b/arch/s390/kvm/gaccess.h
> > @@ -193,6 +193,12 @@ int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u
> >   int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
> >   		    unsigned long length, enum gacc_mode mode, u8 access_key);
> >   
> > +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,
> > +		    enum gacc_mode mode, u8 access_key);
> > +
> > +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,
> > +			      unsigned long len, enum gacc_mode mode, u8 access_key);
> > +
> >   int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
> >   			  void *data, unsigned long len, enum gacc_mode mode,
> >   			  u8 access_key);
> > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> > index 85763ec7bc60..7ee3d2e8ecf2 100644
> > --- a/arch/s390/kvm/kvm-s390.c
> > +++ b/arch/s390/kvm/kvm-s390.c
> > @@ -2365,6 +2365,76 @@ static bool access_key_invalid(u8 access_key)
> >   	return access_key > 0xf;
> >   }
> >   
> > +static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop)
> > +{
> > +	void __user *uaddr = (void __user *)mop->buf;
> > +	u64 supported_flags;
> > +	void *tmpbuf = NULL;
> > +	int r, srcu_idx;
> > +
> > +	supported_flags = KVM_S390_MEMOP_F_SKEY_PROTECTION
> > +			  | KVM_S390_MEMOP_F_CHECK_ONLY;
> > +	if (mop->flags & ~supported_flags)
> > +		return -EINVAL;
> > +	if (mop->size > MEM_OP_MAX_SIZE)
> > +		return -E2BIG;
> > +	if (kvm_s390_pv_is_protected(kvm))
> > +		return -EINVAL;
> > +	if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) {
> > +		if (access_key_invalid(mop->key))
> > +			return -EINVAL;
> > +	}
> > +	if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
> > +		tmpbuf = vmalloc(mop->size);
> > +		if (!tmpbuf)
> > +			return -ENOMEM;
> > +	}
> > +
> > +	srcu_idx = srcu_read_lock(&kvm->srcu);
> > +
> > +	if (kvm_is_error_gpa(kvm, mop->gaddr)) {
> > +		r = PGM_ADDRESSING;
> > +		goto out_unlock;
> > +	}
> > +
> > +	switch (mop->op) {
> > +	case KVM_S390_MEMOP_ABSOLUTE_READ: {
> > +		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
> > +			r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_FETCH, mop->key);
> > +		} else {
> > +			r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
> > +						      mop->size, GACC_FETCH, mop->key);
> > +			if (r == 0) {
> > +				if (copy_to_user(uaddr, tmpbuf, mop->size))
> > +					r = -EFAULT;
> > +			}
> > +		}
> > +		break;
> > +	}
> > +	case KVM_S390_MEMOP_ABSOLUTE_WRITE: {
> > +		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
> > +			r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_STORE, mop->key);
> > +		} else {
> > +			if (copy_from_user(tmpbuf, uaddr, mop->size)) {
> > +				r = -EFAULT;
> > +				break;
> > +			}
> > +			r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
> > +						      mop->size, GACC_STORE, mop->key);
> > +		}
> > +		break;
> > +	}
> > +	default:
> > +		r = -EINVAL;
> > +	}
> > +
> > +out_unlock:
> > +	srcu_read_unlock(&kvm->srcu, srcu_idx);
> > +
> > +	vfree(tmpbuf);
> > +	return r;
> > +}
> > +
> >   long kvm_arch_vm_ioctl(struct file *filp,
> >   		       unsigned int ioctl, unsigned long arg)
> >   {
> > @@ -2489,6 +2559,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
> >   		}
> >   		break;
> >   	}
> > +	case KVM_S390_MEM_OP: {
> > +		struct kvm_s390_mem_op mem_op;
> > +
> > +		if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
> > +			r = kvm_s390_vm_mem_op(kvm, &mem_op);
> > +		else
> > +			r = -EFAULT;
> > +		break;
> > +	}
> >   	default:
> >   		r = -ENOTTY;
> >   	}
> > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > index 44558cf4c52e..b83c9286e017 100644
> > --- a/include/uapi/linux/kvm.h
> > +++ b/include/uapi/linux/kvm.h
> > @@ -575,6 +575,8 @@ struct kvm_s390_mem_op {
> >   #define KVM_S390_MEMOP_LOGICAL_WRITE	1
> >   #define KVM_S390_MEMOP_SIDA_READ	2
> >   #define KVM_S390_MEMOP_SIDA_WRITE	3
> > +#define KVM_S390_MEMOP_ABSOLUTE_READ	4
> > +#define KVM_S390_MEMOP_ABSOLUTE_WRITE	5
> >   /* flags for kvm_s390_mem_op->flags */
> >   #define KVM_S390_MEMOP_F_CHECK_ONLY		(1ULL << 0)
> >   #define KVM_S390_MEMOP_F_INJECT_EXCEPTION	(1ULL << 1)  


  reply	other threads:[~2022-02-10 16:26 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-09 17:04 [PATCH v3 00/10] KVM: s390: Do storage key checking Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 01/10] s390/uaccess: Add copy_from/to_user_key functions Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 02/10] KVM: s390: Honor storage keys when accessing guest memory Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 03/10] KVM: s390: handle_tprot: Honor storage keys Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 04/10] KVM: s390: selftests: Test TEST PROTECTION emulation Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 05/10] KVM: s390: Add optional storage key checking to MEMOP IOCTL Janis Schoetterl-Glausch
2022-02-10  9:29   ` Christian Borntraeger
2022-02-10  9:40     ` Janis Schoetterl-Glausch
2022-02-10  9:43       ` Christian Borntraeger
2022-02-11  8:53     ` Janosch Frank
2022-02-10 11:59   ` Janis Schoetterl-Glausch
2022-02-10 16:33     ` Claudio Imbrenda
2022-02-09 17:04 ` [PATCH v3 06/10] KVM: s390: Add vm IOCTL for key checked guest absolute memory access Janis Schoetterl-Glausch
2022-02-10 14:40   ` Christian Borntraeger
2022-02-10 16:25     ` Claudio Imbrenda [this message]
2022-02-09 17:04 ` [PATCH v3 07/10] KVM: s390: Rename existing vcpu memop functions Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 08/10] KVM: s390: Add capability for storage key extension of MEM_OP IOCTL Janis Schoetterl-Glausch
2022-02-09 17:04 ` [PATCH v3 09/10] KVM: s390: Update api documentation for memop ioctl Janis Schoetterl-Glausch
2022-02-10 14:41   ` Christian Borntraeger
2022-02-11  9:17   ` Janosch Frank
2022-02-09 17:04 ` [PATCH v3 10/10] KVM: s390: selftests: Test memops with storage keys Janis Schoetterl-Glausch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220210172555.43141947@p-imbrenda \
    --to=imbrenda@linux.ibm.com \
    --cc=agordeev@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=corbet@lwn.net \
    --cc=david@redhat.com \
    --cc=frankja@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=scgl@linux.ibm.com \
    --cc=svens@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox