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

[Xen-changelog] Fix locking in /dev/xen/evtchn ioctl.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID e69413dca6844c87885121a7360fa7c2b11cdea9
# Parent  801b2bd7ef2ef3a200b1034d363b429a01a08896
Fix locking in /dev/xen/evtchn ioctl.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 801b2bd7ef2e -r e69413dca684 
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Sat Oct  8 08:54:06 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c  Sat Oct  8 09:22:01 2005
@@ -206,6 +206,15 @@
        return rc;
 }
 
+static void evtchn_bind_to_user(struct per_user_data *u, int port)
+{
+       spin_lock_irq(&port_user_lock);
+       BUG_ON(port_user[port] != NULL);
+       port_user[port] = u;
+       unmask_evtchn(port);
+       spin_unlock_irq(&port_user_lock);
+}
+
 static int evtchn_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
@@ -213,8 +222,6 @@
        struct per_user_data *u = file->private_data;
        evtchn_op_t op = { 0 };
 
-       spin_lock_irq(&port_user_lock);
-    
        switch (cmd) {
        case IOCTL_EVTCHN_BIND_VIRQ: {
                struct ioctl_evtchn_bind_virq bind;
@@ -231,8 +238,7 @@
                        break;
 
                rc = op.u.bind_virq.port;
-               port_user[rc] = u;
-               unmask_evtchn(rc);
+               evtchn_bind_to_user(u, rc);
                break;
        }
 
@@ -251,8 +257,7 @@
                        break;
 
                rc = op.u.bind_interdomain.local_port;
-               port_user[rc] = u;
-               unmask_evtchn(rc);
+               evtchn_bind_to_user(u, rc);
                break;
        }
 
@@ -271,8 +276,7 @@
                        break;
 
                rc = op.u.alloc_unbound.port;
-               port_user[rc] = u;
-               unmask_evtchn(rc);
+               evtchn_bind_to_user(u, rc);
                break;
        }
 
@@ -283,20 +287,28 @@
                if (copy_from_user(&unbind, (void *)arg, sizeof(unbind)))
                        break;
 
-               if (unbind.port >= NR_EVENT_CHANNELS) {
-                       rc = -EINVAL;
-               } else if (port_user[unbind.port] != u) {
-                       rc = -ENOTCONN;
-               } else {
-                       port_user[unbind.port] = NULL;
-                       mask_evtchn(unbind.port);
-
-                       op.cmd = EVTCHNOP_close;
-                       op.u.close.port = unbind.port;
-                       BUG_ON(HYPERVISOR_event_channel_op(&op));
-
-                       rc = 0;
-               }
+               rc = -EINVAL;
+               if (unbind.port >= NR_EVENT_CHANNELS)
+                       break;
+
+               spin_lock_irq(&port_user_lock);
+    
+               rc = -ENOTCONN;
+               if (port_user[unbind.port] != u) {
+                       spin_unlock_irq(&port_user_lock);
+                       break;
+               }
+
+               port_user[unbind.port] = NULL;
+               mask_evtchn(unbind.port);
+
+               spin_unlock_irq(&port_user_lock);
+
+               op.cmd = EVTCHNOP_close;
+               op.u.close.port = unbind.port;
+               BUG_ON(HYPERVISOR_event_channel_op(&op));
+
+               rc = 0;
                break;
        }
 
@@ -320,7 +332,9 @@
 
        case IOCTL_EVTCHN_RESET: {
                /* Initialise the ring to empty. Clear errors. */
+               spin_lock_irq(&port_user_lock);
                u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+               spin_unlock_irq(&port_user_lock);
                rc = 0;
                break;
        }
@@ -329,8 +343,6 @@
                rc = -ENOSYS;
                break;
        }
-
-       spin_unlock_irq(&port_user_lock);   
 
        return rc;
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.