CAPI: Fix racy capi_read
authorJan Kiszka <jan.kiszka@web.de>
Mon, 8 Feb 2010 10:12:21 +0000 (10:12 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 17 Feb 2010 00:01:25 +0000 (16:01 -0800)
capi_read still used interruptible_sleep_on, risking to miss a wakeup
this way. Convert it to wait_event_interruptible.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/isdn/capi/capi.c

index f8f86602c57ee61fcdaae7cd7de141edec7ce20a..8abec9655e1a91983b7ab9485a8da25fe233952d 100644 (file)
@@ -657,24 +657,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        struct capidev *cdev = (struct capidev *)file->private_data;
        struct sk_buff *skb;
        size_t copied;
+       int err;
 
        if (!cdev->ap.applid)
                return -ENODEV;
 
-       if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) {
-
+       skb = skb_dequeue(&cdev->recvqueue);
+       if (!skb) {
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
-
-               for (;;) {
-                       interruptible_sleep_on(&cdev->recvwait);
-                       if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL)
-                               break;
-                       if (signal_pending(current))
-                               break;
-               }
-               if (skb == NULL)
-                       return -ERESTARTNOHAND;
+               err = wait_event_interruptible(cdev->recvwait,
+                               (skb = skb_dequeue(&cdev->recvqueue)));
+               if (err)
+                       return err;
        }
        if (skb->len > count) {
                skb_queue_head(&cdev->recvqueue, skb);