| From d98ee2a19c3334e9343df3ce254b496f1fc428eb Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Tue, 22 Oct 2019 16:32:02 +0200 |
| Subject: USB: ldusb: fix ring-buffer locking |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit d98ee2a19c3334e9343df3ce254b496f1fc428eb upstream. |
| |
| The custom ring-buffer implementation was merged without any locking or |
| explicit memory barriers, but a spinlock was later added by commit |
| 9d33efd9a791 ("USB: ldusb bugfix"). |
| |
| The lock did not cover the update of the tail index once the entry had |
| been processed, something which could lead to memory corruption on |
| weakly ordered architectures or due to compiler optimisations. |
| |
| Specifically, a completion handler running on another CPU might observe |
| the incremented tail index and update the entry before ld_usb_read() is |
| done with it. |
| |
| Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") |
| Fixes: 9d33efd9a791 ("USB: ldusb bugfix") |
| Cc: stable <stable@vger.kernel.org> # 2.6.13 |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Link: https://lore.kernel.org/r/20191022143203.5260-2-johan@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/misc/ldusb.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/usb/misc/ldusb.c |
| +++ b/drivers/usb/misc/ldusb.c |
| @@ -498,11 +498,11 @@ static ssize_t ld_usb_read(struct file * |
| retval = -EFAULT; |
| goto unlock_exit; |
| } |
| - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; |
| - |
| retval = bytes_to_read; |
| |
| spin_lock_irq(&dev->rbsl); |
| + dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; |
| + |
| if (dev->buffer_overflow) { |
| dev->buffer_overflow = 0; |
| spin_unlock_irq(&dev->rbsl); |