firewire: cdev: fix race in iso context creation
authorClemens Ladisch <clemens@ladisch.de>
Mon, 14 Jun 2010 09:46:25 +0000 (11:46 +0200)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Sun, 20 Jun 2010 21:11:56 +0000 (23:11 +0200)
Protect the client's iso context pointer against a race that can happen
when more than one creation call is executed at the same time.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
drivers/firewire/core-cdev.c

index 4e0478d70d4d2959277c07efd86917304ad8a592..ce8cb6fcbbcd67f7c441a6998a325dae8037047e 100644 (file)
@@ -864,10 +864,6 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
        struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
        struct fw_iso_context *context;
 
-       /* We only support one context at this time. */
-       if (client->iso_context != NULL)
-               return -EBUSY;
-
        if (a->channel > 63)
                return -EINVAL;
 
@@ -892,10 +888,17 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
        if (IS_ERR(context))
                return PTR_ERR(context);
 
+       /* We only support one context at this time. */
+       spin_lock_irq(&client->lock);
+       if (client->iso_context != NULL) {
+               spin_unlock_irq(&client->lock);
+               fw_iso_context_destroy(context);
+               return -EBUSY;
+       }
        client->iso_closure = a->closure;
        client->iso_context = context;
+       spin_unlock_irq(&client->lock);
 
-       /* We only support one context at this time. */
        a->handle = 0;
 
        return 0;