Skip to content

Commit e587a76

Browse files
oneukumgregkh
authored andcommitted
usb: gadget: printer: fix races against disable
printer_read() and printer_write() guard against the race against disable() by checking the dev->interface flag, which in turn is guarded by a spinlock. These functions, however, drop the lock on multiple occasions. This means that the test has to be redone after reacquiring the lock and before doing IO. Add the tests. This also addresses CVE-2024-25741 Fixes: 7f2ca14 ("usb: gadget: function: printer: Interface is disabled and returns error") Cc: stable <[email protected]> Signed-off-by: Oliver Neukum <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fd80731 commit e587a76

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

drivers/usb/gadget/function/f_printer.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -450,18 +450,18 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
450450
mutex_lock(&dev->lock_printer_io);
451451
spin_lock_irqsave(&dev->lock, flags);
452452

453-
if (dev->interface < 0) {
454-
spin_unlock_irqrestore(&dev->lock, flags);
455-
mutex_unlock(&dev->lock_printer_io);
456-
return -ENODEV;
457-
}
453+
if (dev->interface < 0)
454+
goto out_disabled;
458455

459456
/* We will use this flag later to check if a printer reset happened
460457
* after we turn interrupts back on.
461458
*/
462459
dev->reset_printer = 0;
463460

464461
setup_rx_reqs(dev);
462+
/* this dropped the lock - need to retest */
463+
if (dev->interface < 0)
464+
goto out_disabled;
465465

466466
bytes_copied = 0;
467467
current_rx_req = dev->current_rx_req;
@@ -495,6 +495,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
495495
wait_event_interruptible(dev->rx_wait,
496496
(likely(!list_empty(&dev->rx_buffers))));
497497
spin_lock_irqsave(&dev->lock, flags);
498+
if (dev->interface < 0)
499+
goto out_disabled;
498500
}
499501

500502
/* We have data to return then copy it to the caller's buffer.*/
@@ -538,6 +540,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
538540
return -EAGAIN;
539541
}
540542

543+
if (dev->interface < 0)
544+
goto out_disabled;
545+
541546
/* If we not returning all the data left in this RX request
542547
* buffer then adjust the amount of data left in the buffer.
543548
* Othewise if we are done with this RX request buffer then
@@ -567,6 +572,11 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
567572
return bytes_copied;
568573
else
569574
return -EAGAIN;
575+
576+
out_disabled:
577+
spin_unlock_irqrestore(&dev->lock, flags);
578+
mutex_unlock(&dev->lock_printer_io);
579+
return -ENODEV;
570580
}
571581

572582
static ssize_t
@@ -587,11 +597,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
587597
mutex_lock(&dev->lock_printer_io);
588598
spin_lock_irqsave(&dev->lock, flags);
589599

590-
if (dev->interface < 0) {
591-
spin_unlock_irqrestore(&dev->lock, flags);
592-
mutex_unlock(&dev->lock_printer_io);
593-
return -ENODEV;
594-
}
600+
if (dev->interface < 0)
601+
goto out_disabled;
595602

596603
/* Check if a printer reset happens while we have interrupts on */
597604
dev->reset_printer = 0;
@@ -614,6 +621,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
614621
wait_event_interruptible(dev->tx_wait,
615622
(likely(!list_empty(&dev->tx_reqs))));
616623
spin_lock_irqsave(&dev->lock, flags);
624+
if (dev->interface < 0)
625+
goto out_disabled;
617626
}
618627

619628
while (likely(!list_empty(&dev->tx_reqs)) && len) {
@@ -663,6 +672,9 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
663672
return -EAGAIN;
664673
}
665674

675+
if (dev->interface < 0)
676+
goto out_disabled;
677+
666678
list_add(&req->list, &dev->tx_reqs_active);
667679

668680
/* here, we unlock, and only unlock, to avoid deadlock. */
@@ -675,6 +687,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
675687
mutex_unlock(&dev->lock_printer_io);
676688
return -EAGAIN;
677689
}
690+
if (dev->interface < 0)
691+
goto out_disabled;
678692
}
679693

680694
spin_unlock_irqrestore(&dev->lock, flags);
@@ -686,6 +700,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
686700
return bytes_copied;
687701
else
688702
return -EAGAIN;
703+
704+
out_disabled:
705+
spin_unlock_irqrestore(&dev->lock, flags);
706+
mutex_unlock(&dev->lock_printer_io);
707+
return -ENODEV;
689708
}
690709

691710
static int

0 commit comments

Comments
 (0)