All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>,
	rusty@rustcorp.com.au, Al Viro <viro@zeniv.linux.org.uk>,
	kvm@vger.kernel.org, virtualization@lists.osdl.org
Subject: [PATCH] vhost: access check thinko fixes
Date: Thu, 24 Dec 2009 08:00:58 +0200	[thread overview]
Message-ID: <20091224060058.GA26101@redhat.com> (raw)

This fixes two issues with recent access checking patch:
1.  if (&d->vqs[i].private_data) -> if (d->vqs[i].private_data)
2.  we can't forbid log base changes while ring is running,
    because host needs to resize log in rare cases
    (e.g. when memory is added with a baloon)
    and in that case it needs to increase log size with realloc,
    which might move the log address.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---

Rusty, this needs to be applied on top of the access_ok patch.
If you want me to rool it in with that one and esend, let me
know please.
Thanks!

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

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 2b65d9b..c8c25db 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -230,7 +230,7 @@ static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
 }
 
 /* Caller should have vq mutex and device mutex. */
-static int vq_memory_access_ok(struct vhost_virtqueue *vq, struct vhost_memory *mem,
+static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem,
 			       int log_all)
 {
 	int i;
@@ -242,7 +242,7 @@ static int vq_memory_access_ok(struct vhost_virtqueue *vq, struct vhost_memory *
 		else if (!access_ok(VERIFY_WRITE, (void __user *)a,
 				    m->memory_size))
 			return 0;
-		else if (log_all && !log_access_ok(vq->log_base,
+		else if (log_all && !log_access_ok(log_base,
 						   m->guest_phys_addr,
 						   m->memory_size))
 			return 0;
@@ -259,9 +259,10 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
 	for (i = 0; i < d->nvqs; ++i) {
 		int ok;
 		mutex_lock(&d->vqs[i].mutex);
-		/* If ring is not running, will check when it's enabled. */
-		if (&d->vqs[i].private_data)
-			ok = vq_memory_access_ok(&d->vqs[i], mem, log_all);
+		/* If ring is inactive, will check when it's enabled. */
+		if (d->vqs[i].private_data)
+			ok = vq_memory_access_ok(d->vqs[i].log_base, mem,
+						 log_all);
 		else
 			ok = 1;
 		mutex_unlock(&d->vqs[i].mutex);
@@ -290,18 +291,25 @@ int vhost_log_access_ok(struct vhost_dev *dev)
 	return memory_access_ok(dev, dev->memory, 1);
 }
 
-/* Can we start vq? */
+/* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
-int vhost_vq_access_ok(struct vhost_virtqueue *vq)
+static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base)
 {
-	return vq_access_ok(vq->num, vq->desc, vq->avail, vq->used) &&
-		vq_memory_access_ok(vq, vq->dev->memory,
+	return vq_memory_access_ok(log_base, vq->dev->memory,
 			    vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) &&
-		(!vq->log_used || log_access_ok(vq->log_base, vq->log_addr,
+		(!vq->log_used || log_access_ok(log_base, vq->log_addr,
 					sizeof *vq->used +
 					vq->num * sizeof *vq->used->ring));
 }
 
+/* Can we start vq? */
+/* Caller should have vq mutex and device mutex */
+int vhost_vq_access_ok(struct vhost_virtqueue *vq)
+{
+	return vq_access_ok(vq->num, vq->desc, vq->avail, vq->used) &&
+		vq_log_access_ok(vq, vq->log_base);
+}
+
 static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 {
 	struct vhost_memory mem, *newmem, *oldmem;
@@ -564,15 +572,14 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
 		}
 		for (i = 0; i < d->nvqs; ++i) {
 			struct vhost_virtqueue *vq;
+			void __user *base = (void __user *)(unsigned long)p;
 			vq = d->vqs + i;
 			mutex_lock(&vq->mutex);
-			/* Moving log base with an active backend?
-			 * You don't want to do that. */
-			if (vq->private_data && (vq->log_used ||
-			     vhost_has_feature(d, VHOST_F_LOG_ALL)))
-				r = -EBUSY;
+			/* If ring is inactive, will check when it's enabled. */
+			if (vq->private_data && !vq_log_access_ok(vq, base))
+				r = -EFAULT;
 			else
-				vq->log_base = (void __user *)(unsigned long)p;
+				vq->log_base = base;
 			mutex_unlock(&vq->mutex);
 		}
 		break;
-- 
1.6.6.rc1.43.gf55cc

             reply	other threads:[~2009-12-24  6:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-24  6:00 Michael S. Tsirkin [this message]
2010-01-04  2:22 ` [PATCH] vhost: access check thinko fixes Rusty Russell

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=20091224060058.GA26101@redhat.com \
    --to=mst@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=rusty@rustcorp.com.au \
    --cc=viro@zeniv.linux.org.uk \
    --cc=virtualization@lists.osdl.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.