linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] vhost: Skip access checks on GIOVAs
@ 2020-10-03 10:01 Greg Kurz
  2020-10-03 10:01 ` [PATCH v3 1/3] vhost: Don't call access_ok() when using IOTLB Greg Kurz
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Greg Kurz @ 2020-10-03 10:01 UTC (permalink / raw)
  To: Michael S. Tsirkin, Jason Wang
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson

This series addresses some misuse around vring addresses provided by
userspace when using an IOTLB device. The misuse cause failures of
the VHOST_SET_VRING_ADDR ioctl on POWER, which in turn causes QEMU
to crash at migration time.

Jason suggested that we should use vhost_get_used_size() during the
review of v2. Fixed this in a preliminary patch (patch 2) and rebased
the vq_log_used_access_ok() helper on top (patch 3).

Note that I've also posted a patch for QEMU so that it skips the used
structure GIOVA when allocating the log bitmap. Otherwise QEMU fails to
allocate it because POWER puts GIOVAs very high in the address space (ie.
over 0x800000000000000ULL).

https://patchwork.ozlabs.org/project/qemu-devel/patch/160105498386.68108.2145229309875282336.stgit@bahia.lan/

v3:
 - patch 1: added Jason's ack
 - patch 2: new patch to use vhost_get_used_size()
 - patch 3: rebased patch 2 from v2

v2:
 - patch 1: move the (vq->ioltb) check from vhost_vq_access_ok() to
            vq_access_ok() as suggested by MST
 - patch 2: new patch

---

Greg Kurz (3):
      vhost: Don't call access_ok() when using IOTLB
      vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
      vhost: Don't call log_access_ok() when using IOTLB


 drivers/vhost/vhost.c |   33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

--
Greg


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/3] vhost: Don't call access_ok() when using IOTLB
  2020-10-03 10:01 [PATCH v3 0/3] vhost: Skip access checks on GIOVAs Greg Kurz
@ 2020-10-03 10:01 ` Greg Kurz
  2020-10-03 10:02 ` [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr() Greg Kurz
  2020-10-03 10:02 ` [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB Greg Kurz
  2 siblings, 0 replies; 7+ messages in thread
From: Greg Kurz @ 2020-10-03 10:01 UTC (permalink / raw)
  To: Michael S. Tsirkin, Jason Wang
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson

When the IOTLB device is enabled, the vring addresses we get
from userspace are GIOVAs. It is thus wrong to pass them down
to access_ok() which only takes HVAs.

Access validation is done at prefetch time with IOTLB. Teach
vq_access_ok() about that by moving the (vq->iotlb) check
from vhost_vq_access_ok() to vq_access_ok(). This prevents
vhost_vring_set_addr() to fail when verifying the accesses.
No behavior change for vhost_vq_access_ok().

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1883084
Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API")
Cc: jasowang@redhat.com
CC: stable@vger.kernel.org # 4.14+
Signed-off-by: Greg Kurz <groug@kaod.org>
Acked-by: Jason Wang <jasowang@redhat.com>
---
 drivers/vhost/vhost.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index b45519ca66a7..c3b49975dc28 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1290,6 +1290,11 @@ static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num,
 			 vring_used_t __user *used)
 
 {
+	/* If an IOTLB device is present, the vring addresses are
+	 * GIOVAs. Access validation occurs at prefetch time. */
+	if (vq->iotlb)
+		return true;
+
 	return access_ok(desc, vhost_get_desc_size(vq, num)) &&
 	       access_ok(avail, vhost_get_avail_size(vq, num)) &&
 	       access_ok(used, vhost_get_used_size(vq, num));
@@ -1383,10 +1388,6 @@ bool vhost_vq_access_ok(struct vhost_virtqueue *vq)
 	if (!vq_log_access_ok(vq, vq->log_base))
 		return false;
 
-	/* Access validation occurs at prefetch time with IOTLB */
-	if (vq->iotlb)
-		return true;
-
 	return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used);
 }
 EXPORT_SYMBOL_GPL(vhost_vq_access_ok);



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
  2020-10-03 10:01 [PATCH v3 0/3] vhost: Skip access checks on GIOVAs Greg Kurz
  2020-10-03 10:01 ` [PATCH v3 1/3] vhost: Don't call access_ok() when using IOTLB Greg Kurz
@ 2020-10-03 10:02 ` Greg Kurz
  2020-10-10  2:32   ` Jason Wang
  2020-10-03 10:02 ` [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB Greg Kurz
  2 siblings, 1 reply; 7+ messages in thread
From: Greg Kurz @ 2020-10-03 10:02 UTC (permalink / raw)
  To: Michael S. Tsirkin, Jason Wang
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson

The open-coded computation of the used size doesn't take the event
into account when the VIRTIO_RING_F_EVENT_IDX feature is present.
Fix that by using vhost_get_used_size().

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 drivers/vhost/vhost.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c3b49975dc28..9d2c225fb518 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1519,8 +1519,7 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
 		/* Also validate log access for used ring if enabled. */
 		if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
 			!log_access_ok(vq->log_base, a.log_guest_addr,
-				sizeof *vq->used +
-				vq->num * sizeof *vq->used->ring))
+				       vhost_get_used_size(vq, vq->num)))
 			return -EINVAL;
 	}
 



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB
  2020-10-03 10:01 [PATCH v3 0/3] vhost: Skip access checks on GIOVAs Greg Kurz
  2020-10-03 10:01 ` [PATCH v3 1/3] vhost: Don't call access_ok() when using IOTLB Greg Kurz
  2020-10-03 10:02 ` [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr() Greg Kurz
@ 2020-10-03 10:02 ` Greg Kurz
  2020-10-10  3:00   ` Jason Wang
  2 siblings, 1 reply; 7+ messages in thread
From: Greg Kurz @ 2020-10-03 10:02 UTC (permalink / raw)
  To: Michael S. Tsirkin, Jason Wang
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson

When the IOTLB device is enabled, the log_guest_addr that is passed by
userspace to the VHOST_SET_VRING_ADDR ioctl, and which is then written
to vq->log_addr, is a GIOVA. All writes to this address are translated
by log_user() to writes to an HVA, and then ultimately logged through
the corresponding GPAs in log_write_hva(). No logging will ever occur
with vq->log_addr in this case. It is thus wrong to pass vq->log_addr
and log_guest_addr to log_access_vq() which assumes they are actual
GPAs.

Introduce a new vq_log_used_access_ok() helper that only checks accesses
to the log for the used structure when there isn't an IOTLB device around.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 drivers/vhost/vhost.c |   23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9d2c225fb518..9ad45e1d27f0 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1370,6 +1370,20 @@ bool vhost_log_access_ok(struct vhost_dev *dev)
 }
 EXPORT_SYMBOL_GPL(vhost_log_access_ok);
 
+static bool vq_log_used_access_ok(struct vhost_virtqueue *vq,
+				  void __user *log_base,
+				  bool log_used,
+				  u64 log_addr)
+{
+	/* If an IOTLB device is present, log_addr is a GIOVA that
+	 * will never be logged by log_used(). */
+	if (vq->iotlb)
+		return true;
+
+	return !log_used || log_access_ok(log_base, log_addr,
+					  vhost_get_used_size(vq, vq->num));
+}
+
 /* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
 static bool vq_log_access_ok(struct vhost_virtqueue *vq,
@@ -1377,8 +1391,7 @@ static bool vq_log_access_ok(struct vhost_virtqueue *vq,
 {
 	return vq_memory_access_ok(log_base, vq->umem,
 				   vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
-		(!vq->log_used || log_access_ok(log_base, vq->log_addr,
-				  vhost_get_used_size(vq, vq->num)));
+		vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr);
 }
 
 /* Can we start vq? */
@@ -1517,9 +1530,9 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
 			return -EINVAL;
 
 		/* Also validate log access for used ring if enabled. */
-		if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
-			!log_access_ok(vq->log_base, a.log_guest_addr,
-				       vhost_get_used_size(vq, vq->num)))
+		if (!vq_log_used_access_ok(vq, vq->log_base,
+				a.flags & (0x1 << VHOST_VRING_F_LOG),
+				a.log_guest_addr))
 			return -EINVAL;
 	}
 



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
  2020-10-03 10:02 ` [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr() Greg Kurz
@ 2020-10-10  2:32   ` Jason Wang
  2020-10-11  6:46     ` Michael S. Tsirkin
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Wang @ 2020-10-10  2:32 UTC (permalink / raw)
  To: Greg Kurz, Michael S. Tsirkin
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson


On 2020/10/3 下午6:02, Greg Kurz wrote:
> The open-coded computation of the used size doesn't take the event
> into account when the VIRTIO_RING_F_EVENT_IDX feature is present.
> Fix that by using vhost_get_used_size().
>
> Signed-off-by: Greg Kurz <groug@kaod.org>
> ---
>   drivers/vhost/vhost.c |    3 +--
>   1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index c3b49975dc28..9d2c225fb518 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1519,8 +1519,7 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
>   		/* Also validate log access for used ring if enabled. */
>   		if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
>   			!log_access_ok(vq->log_base, a.log_guest_addr,
> -				sizeof *vq->used +
> -				vq->num * sizeof *vq->used->ring))
> +				       vhost_get_used_size(vq, vq->num)))
>   			return -EINVAL;
>   	}
>   
>
>

Acked-by: Jason Wang <jasowang@redhat.com>



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB
  2020-10-03 10:02 ` [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB Greg Kurz
@ 2020-10-10  3:00   ` Jason Wang
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2020-10-10  3:00 UTC (permalink / raw)
  To: Greg Kurz, Michael S. Tsirkin
  Cc: kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson


On 2020/10/3 下午6:02, Greg Kurz wrote:
> When the IOTLB device is enabled, the log_guest_addr that is passed by
> userspace to the VHOST_SET_VRING_ADDR ioctl, and which is then written
> to vq->log_addr, is a GIOVA. All writes to this address are translated
> by log_user() to writes to an HVA, and then ultimately logged through
> the corresponding GPAs in log_write_hva(). No logging will ever occur
> with vq->log_addr in this case. It is thus wrong to pass vq->log_addr
> and log_guest_addr to log_access_vq() which assumes they are actual
> GPAs.
>
> Introduce a new vq_log_used_access_ok() helper that only checks accesses
> to the log for the used structure when there isn't an IOTLB device around.
>
> Signed-off-by: Greg Kurz <groug@kaod.org>


Acked-by: Jason Wang <jasowang@redhat.com>

In the future, we may consider to deprecate log_guest_addr since in any 
case regardless of IOTLB ennoblement we can get GPA from either IOTLB or 
MEM table.

Thanks


> ---
>   drivers/vhost/vhost.c |   23 ++++++++++++++++++-----
>   1 file changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 9d2c225fb518..9ad45e1d27f0 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1370,6 +1370,20 @@ bool vhost_log_access_ok(struct vhost_dev *dev)
>   }
>   EXPORT_SYMBOL_GPL(vhost_log_access_ok);
>   
> +static bool vq_log_used_access_ok(struct vhost_virtqueue *vq,
> +				  void __user *log_base,
> +				  bool log_used,
> +				  u64 log_addr)
> +{
> +	/* If an IOTLB device is present, log_addr is a GIOVA that
> +	 * will never be logged by log_used(). */
> +	if (vq->iotlb)
> +		return true;
> +
> +	return !log_used || log_access_ok(log_base, log_addr,
> +					  vhost_get_used_size(vq, vq->num));
> +}
> +
>   /* Verify access for write logging. */
>   /* Caller should have vq mutex and device mutex */
>   static bool vq_log_access_ok(struct vhost_virtqueue *vq,
> @@ -1377,8 +1391,7 @@ static bool vq_log_access_ok(struct vhost_virtqueue *vq,
>   {
>   	return vq_memory_access_ok(log_base, vq->umem,
>   				   vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
> -		(!vq->log_used || log_access_ok(log_base, vq->log_addr,
> -				  vhost_get_used_size(vq, vq->num)));
> +		vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr);
>   }
>   
>   /* Can we start vq? */
> @@ -1517,9 +1530,9 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
>   			return -EINVAL;
>   
>   		/* Also validate log access for used ring if enabled. */
> -		if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
> -			!log_access_ok(vq->log_base, a.log_guest_addr,
> -				       vhost_get_used_size(vq, vq->num)))
> +		if (!vq_log_used_access_ok(vq, vq->log_base,
> +				a.flags & (0x1 << VHOST_VRING_F_LOG),
> +				a.log_guest_addr))
>   			return -EINVAL;
>   	}
>   
>
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
  2020-10-10  2:32   ` Jason Wang
@ 2020-10-11  6:46     ` Michael S. Tsirkin
  0 siblings, 0 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2020-10-11  6:46 UTC (permalink / raw)
  To: Jason Wang
  Cc: Greg Kurz, kvm, virtualization, netdev, linux-kernel, qemu-devel,
	Laurent Vivier, David Gibson

On Sat, Oct 10, 2020 at 10:32:13AM +0800, Jason Wang wrote:
> 
> On 2020/10/3 下午6:02, Greg Kurz wrote:
> > The open-coded computation of the used size doesn't take the event
> > into account when the VIRTIO_RING_F_EVENT_IDX feature is present.
> > Fix that by using vhost_get_used_size().
> > 
> > Signed-off-by: Greg Kurz <groug@kaod.org>
> > ---
> >   drivers/vhost/vhost.c |    3 +--
> >   1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index c3b49975dc28..9d2c225fb518 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -1519,8 +1519,7 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
> >   		/* Also validate log access for used ring if enabled. */
> >   		if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
> >   			!log_access_ok(vq->log_base, a.log_guest_addr,
> > -				sizeof *vq->used +
> > -				vq->num * sizeof *vq->used->ring))
> > +				       vhost_get_used_size(vq, vq->num)))
> >   			return -EINVAL;
> >   	}
> > 
> > 
> 
> Acked-by: Jason Wang <jasowang@redhat.com>

Linus already merged this, I can't add your ack, sorry!


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-10-11  6:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-03 10:01 [PATCH v3 0/3] vhost: Skip access checks on GIOVAs Greg Kurz
2020-10-03 10:01 ` [PATCH v3 1/3] vhost: Don't call access_ok() when using IOTLB Greg Kurz
2020-10-03 10:02 ` [PATCH v3 2/3] vhost: Use vhost_get_used_size() in vhost_vring_set_addr() Greg Kurz
2020-10-10  2:32   ` Jason Wang
2020-10-11  6:46     ` Michael S. Tsirkin
2020-10-03 10:02 ` [PATCH v3 3/3] vhost: Don't call log_access_ok() when using IOTLB Greg Kurz
2020-10-10  3:00   ` Jason Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).