[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |