diff mbox series

[1/2] USB: cdc-acm: fix racy tty buffer accesses

Message ID 20210929090937.7410-2-johan@kernel.org (mailing list archive)
State Accepted
Commit 65a205e6113506e69a503b61d97efec43fc10fd7
Headers show
Series USB: cdc-acm: fix break reporting | expand

Commit Message

Johan Hovold Sept. 29, 2021, 9:09 a.m. UTC
A recent change that started reporting break events to the line
discipline caused the tty-buffer insertions to no longer be serialised
by inserting events also from the completion handler for the interrupt
endpoint.

Completion calls for distinct endpoints are not guaranteed to be
serialised. For example, in case a host-controller driver uses
bottom-half completion, the interrupt and bulk-in completion handlers
can end up running in parallel on two CPUs (high-and low-prio tasklets,
respectively) thereby breaking the tty layer's single producer
assumption.

Fix this by holding the read lock also when inserting characters from
the bulk endpoint.

Fixes: 08dff274edda ("cdc-acm: fix BREAK rx code path adding necessary calls")
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
---
 drivers/usb/class/cdc-acm.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Oliver Neukum Sept. 30, 2021, 9:04 a.m. UTC | #1
On 29.09.21 11:09, Johan Hovold wrote:
> A recent change that started reporting break events to the line
> discipline caused the tty-buffer insertions to no longer be serialised
> by inserting events also from the completion handler for the interrupt
> endpoint.
>
> Completion calls for distinct endpoints are not guaranteed to be
> serialised. For example, in case a host-controller driver uses
> bottom-half completion, the interrupt and bulk-in completion handlers
> can end up running in parallel on two CPUs (high-and low-prio tasklets,
> respectively) thereby breaking the tty layer's single producer
> assumption.
>
> Fix this by holding the read lock also when inserting characters from
> the bulk endpoint.
>
> Fixes: 08dff274edda ("cdc-acm: fix BREAK rx code path adding necessary calls")
> Cc: stable@vger.kernel.org
> Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Oliver Neukum <oneukum@suse.com>
diff mbox series

Patch

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 4e2f1552f4b7..c7a1736720e7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -475,11 +475,16 @@  static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags)
 
 static void acm_process_read_urb(struct acm *acm, struct urb *urb)
 {
+	unsigned long flags;
+
 	if (!urb->actual_length)
 		return;
 
+	spin_lock_irqsave(&acm->read_lock, flags);
 	tty_insert_flip_string(&acm->port, urb->transfer_buffer,
 			urb->actual_length);
+	spin_unlock_irqrestore(&acm->read_lock, flags);
+
 	tty_flip_buffer_push(&acm->port);
 }