public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: gadget: printer: fix races against disable
@ 2024-06-20 11:40 Oliver Neukum
  2024-06-20 12:28 ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Oliver Neukum @ 2024-06-20 11:40 UTC (permalink / raw)
  To: qiang.zhang, ivan.orlov0322, christophe.jaillet, gregkh,
	linux-usb
  Cc: Oliver Neukum

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: 7f2ca14d2f9b9 ("usb: gadget: function: printer: Interface is disabled and returns error")
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/usb/gadget/function/f_printer.c | 39 ++++++++++++++++++-------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 4c0b7c2970f1..44e20c6c36d3 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -450,11 +450,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 	mutex_lock(&dev->lock_printer_io);
 	spin_lock_irqsave(&dev->lock, flags);
 
-	if (dev->interface < 0) {
-		spin_unlock_irqrestore(&dev->lock, flags);
-		mutex_unlock(&dev->lock_printer_io);
-		return -ENODEV;
-	}
+	if (dev->interface < 0)
+		goto out_disabled;
 
 	/* We will use this flag later to check if a printer reset happened
 	 * after we turn interrupts back on.
@@ -462,6 +459,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 	dev->reset_printer = 0;
 
 	setup_rx_reqs(dev);
+	/* this dropped the lock - need to retest */
+	if (dev->interface < 0)
+		goto out_disabled;
 
 	bytes_copied = 0;
 	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)
 		wait_event_interruptible(dev->rx_wait,
 				(likely(!list_empty(&dev->rx_buffers))));
 		spin_lock_irqsave(&dev->lock, flags);
+		if (dev->interface < 0)
+			goto out_disabled;
 	}
 
 	/* 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)
 			return -EAGAIN;
 		}
 
+		if (dev->interface < 0)
+			goto out_disabled;
+
 		/* If we not returning all the data left in this RX request
 		 * buffer then adjust the amount of data left in the buffer.
 		 * 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)
 		return bytes_copied;
 	else
 		return -EAGAIN;
+
+out_disabled:
+	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock_printer_io);
+	return -ENODEV;
 }
 
 static ssize_t
@@ -587,11 +597,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 	mutex_lock(&dev->lock_printer_io);
 	spin_lock_irqsave(&dev->lock, flags);
 
-	if (dev->interface < 0) {
-		spin_unlock_irqrestore(&dev->lock, flags);
-		mutex_unlock(&dev->lock_printer_io);
-		return -ENODEV;
-	}
+	if (dev->interface < 0)
+		goto out_disabled;
 
 	/* Check if a printer reset happens while we have interrupts on */
 	dev->reset_printer = 0;
@@ -614,6 +621,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 		wait_event_interruptible(dev->tx_wait,
 				(likely(!list_empty(&dev->tx_reqs))));
 		spin_lock_irqsave(&dev->lock, flags);
+		if (dev->interface < 0)
+			goto out_disabled;
 	}
 
 	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)
 			return -EAGAIN;
 		}
 
+		if (dev->interface < 0)
+			goto out_disabled;
+
 		list_add(&req->list, &dev->tx_reqs_active);
 
 		/* 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)
 			mutex_unlock(&dev->lock_printer_io);
 			return -EAGAIN;
 		}
+		if (dev->interface < 0)
+			goto out_disabled;
 	}
 
 	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)
 		return bytes_copied;
 	else
 		return -EAGAIN;
+
+out_disabled:
+	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock_printer_io);
+	return -ENODEV;
 }
 
 static int
-- 
2.45.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] usb: gadget: printer: fix races against disable
  2024-06-20 11:40 [PATCH] usb: gadget: printer: fix races against disable Oliver Neukum
@ 2024-06-20 12:28 ` Greg KH
  2024-06-20 13:11   ` Oliver Neukum
  2024-06-20 13:34   ` Greg KH
  0 siblings, 2 replies; 4+ messages in thread
From: Greg KH @ 2024-06-20 12:28 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: qiang.zhang, ivan.orlov0322, christophe.jaillet, linux-usb

On Thu, Jun 20, 2024 at 01:40:26PM +0200, Oliver Neukum wrote:
> 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

What?  Why is MITRE assigning CVEs for the kernel now?  Who asked for
this and who assigned this?  Do I need to go poke someone with a big
stick?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] usb: gadget: printer: fix races against disable
  2024-06-20 12:28 ` Greg KH
@ 2024-06-20 13:11   ` Oliver Neukum
  2024-06-20 13:34   ` Greg KH
  1 sibling, 0 replies; 4+ messages in thread
From: Oliver Neukum @ 2024-06-20 13:11 UTC (permalink / raw)
  To: Greg KH, Oliver Neukum
  Cc: qiang.zhang, ivan.orlov0322, christophe.jaillet, linux-usb

On 20.06.24 14:28, Greg KH wrote:

> What?  Why is MITRE assigning CVEs for the kernel now?  Who asked for
> this and who assigned this?  Do I need to go poke someone with a big
> stick?

I don't know about that. I just get the bug reports and this one
said that the issue is a CVE.

	Regards
		Oliver


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] usb: gadget: printer: fix races against disable
  2024-06-20 12:28 ` Greg KH
  2024-06-20 13:11   ` Oliver Neukum
@ 2024-06-20 13:34   ` Greg KH
  1 sibling, 0 replies; 4+ messages in thread
From: Greg KH @ 2024-06-20 13:34 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: qiang.zhang, ivan.orlov0322, christophe.jaillet, linux-usb

On Thu, Jun 20, 2024 at 02:28:07PM +0200, Greg KH wrote:
> On Thu, Jun 20, 2024 at 01:40:26PM +0200, Oliver Neukum wrote:
> > 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
> 
> What?  Why is MITRE assigning CVEs for the kernel now?  Who asked for
> this and who assigned this?  Do I need to go poke someone with a big
> stick?

Turns out it was allocated 1 day before kernel.org became the CNA, so
false alarm :)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-20 13:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-20 11:40 [PATCH] usb: gadget: printer: fix races against disable Oliver Neukum
2024-06-20 12:28 ` Greg KH
2024-06-20 13:11   ` Oliver Neukum
2024-06-20 13:34   ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox