# 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
|