LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH] 2.4: USB: fix DoS in pwc USB video driver
@ 2008-02-07  2:06 dann frazier
  2008-02-07  4:57 ` Willy Tarreau
  0 siblings, 1 reply; 2+ messages in thread
From: dann frazier @ 2008-02-07  2:06 UTC (permalink / raw)
  To: Willy TARREAU; +Cc: Oliver Neukum, linux-kernel

This is a 2.4 backport of a linux-2.6 change by Oliver Neukum.
(commit 85237f202d46d55c1bffe0c5b1aa3ddc0f1dce4d)

CVE-2007-5093 was assigned for this issue.
This backport has been compile-tested only.

Commit log from 2.6 follows.

  the pwc driver has a disconnect method that waits for user space to
  close the device. This opens up an opportunity for a DoS attack,
  blocking the USB subsystem and making khubd's task busy wait in
  kernel space. This patch shifts freeing resources to close if an opened
  device is disconnected.

Signed-off-by: dann frazier <dannf@hp.com>
---
 drivers/usb/pwc-if.c |   50 +++++++++++++++++++++++++++++++++-----------------
 drivers/usb/pwc.h    |    1 +
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
index e458515..a1c3989 100644
--- a/drivers/usb/pwc-if.c
+++ b/drivers/usb/pwc-if.c
@@ -1055,11 +1055,16 @@ static int pwc_video_open(struct video_device *vdev, int mode)
 	return 0;
 }
 
+static void pwc_cleanup(struct pwc_device *pdev)
+{
+	video_unregister_device(&pdev->vdev);
+}
+
 /* Note that all cleanup is done in the reverse order as in _open */
 static void pwc_video_close(struct video_device *vdev)
 {
 	struct pwc_device *pdev;
-	int i;
+	int i, hint;
 
 	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
 
@@ -1083,8 +1088,9 @@ static void pwc_video_close(struct video_device *vdev)
 	pwc_isoc_cleanup(pdev);
 	pwc_free_buffers(pdev);
 
+	lock_kernel();
 	/* Turn off LEDS and power down camera, but only when not unplugged */
-	if (pdev->error_status != EPIPE) {
+	if (!pdev->unplugged) {
 		if (pwc_set_leds(pdev, 0, 0) < 0)
 			Info("Failed to set LED on/off time.\n");
 		if (power_save) {
@@ -1092,9 +1098,18 @@ static void pwc_video_close(struct video_device *vdev)
 			if (i < 0) 
 				Err("Failed to power down camera (%d)\n", i);
 		}
+		pdev->vopen = 0;
+		Trace(TRACE_OPEN, "<< video_close()\n");
+	} else {
+		pwc_cleanup(pdev);
+		/* Free memory (don't set pdev to 0 just yet) */
+		kfree(pdev);
+		/* search device_hint[] table if we occupy a slot, by any chance */
+		for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+			if (device_hint[hint].pdev == pdev)
+				device_hint[hint].pdev = NULL;
 	}
-	pdev->vopen = 0;
-	Trace(TRACE_OPEN, "<< video_close()\n");
+	unlock_kernel();
 }
 
 /*
@@ -1897,19 +1912,20 @@ static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
 	/* Alert waiting processes */
 	wake_up_interruptible(&pdev->frameq);
 	/* Wait until device is closed */
-	while (pdev->vopen)
-		schedule();
-	/* Device is now closed, so we can safely unregister it */
-	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
-	video_unregister_device(&pdev->vdev); 
-
-	/* Free memory (don't set pdev to 0 just yet) */
-	kfree(pdev);
-
-	/* search device_hint[] table if we occupy a slot, by any chance */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-		if (device_hint[hint].pdev == pdev)
-			device_hint[hint].pdev = NULL;
+	if(pdev->vopen) {
+		pdev->unplugged = 1;
+	} else {
+		/* Device is closed, so we can safely unregister it */
+		Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+		pwc_cleanup(pdev);
+		/* Free memory (don't set pdev to 0 just yet) */
+		kfree(pdev);
+	
+		/* search device_hint[] table if we occupy a slot, by any chance */
+		for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+			if (device_hint[hint].pdev == pdev)
+				device_hint[hint].pdev = NULL;
+	}
 
 	unlock_kernel();
 }
diff --git a/drivers/usb/pwc.h b/drivers/usb/pwc.h
index b020769..999daf2 100644
--- a/drivers/usb/pwc.h
+++ b/drivers/usb/pwc.h
@@ -141,6 +141,7 @@ struct pwc_device
    char vsnapshot;		/* snapshot mode */
    char vsync;			/* used by isoc handler */
    char vmirror;		/* for ToUCaM series */
+	char unplugged;
 
    /* The image acquisition requires 3 to 4 steps:
       1. data is gathered in short packets from the USB controller
-- 
1.5.3.7


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

* Re: [PATCH] 2.4: USB: fix DoS in pwc USB video driver
  2008-02-07  2:06 [PATCH] 2.4: USB: fix DoS in pwc USB video driver dann frazier
@ 2008-02-07  4:57 ` Willy Tarreau
  0 siblings, 0 replies; 2+ messages in thread
From: Willy Tarreau @ 2008-02-07  4:57 UTC (permalink / raw)
  To: dann frazier; +Cc: Oliver Neukum, linux-kernel

On Wed, Feb 06, 2008 at 07:06:18PM -0700, dann frazier wrote:
> This is a 2.4 backport of a linux-2.6 change by Oliver Neukum.
> (commit 85237f202d46d55c1bffe0c5b1aa3ddc0f1dce4d)

That's weird, because I remember about this one I checked while working
on 2.6.20-stable. For an unknown reason, I thought that it did not affect
2.4 version of the driver, and I was apparently wrong :-/

> CVE-2007-5093 was assigned for this issue.
> This backport has been compile-tested only.

I've applied it, and I have such a webcam lying somewhere, so I'll be able
to test.

Thanks Dann!
Willy


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

end of thread, other threads:[~2008-02-07  5:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-07  2:06 [PATCH] 2.4: USB: fix DoS in pwc USB video driver dann frazier
2008-02-07  4:57 ` Willy Tarreau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).