ChangeSet 1.1118, 2003/07/14 13:52:30-07:00, stern@rowland.harvard.edu

[PATCH] USB: usb-storage US_FL_FIX_CAPACITY fix

Pat LaVarre uncovered a bug where you could throw a well-formed (but
arguably meaningless) INQUIRY command at a device via the sg interface
and OOPS the usb-storage driver.  This prevents that from happening.

This has been in 2.5 for a while now.  A 2.4 backport is probably a good
thing.


 drivers/usb/storage/protocol.c |   21 +++++++++++++++------
 drivers/usb/storage/usb.h      |    2 +-
 2 files changed, 16 insertions(+), 7 deletions(-)


diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	Mon Jul 14 14:27:19 2003
+++ b/drivers/usb/storage/protocol.c	Mon Jul 14 14:27:19 2003
@@ -53,9 +53,9 @@
 /***********************************************************************
  * Helper routines
  ***********************************************************************/
-
-static void *
-find_data_location(Scsi_Cmnd *srb) {
+ 
+static void * find_data_location(Scsi_Cmnd *srb)
+{
 	if (srb->use_sg) {
 		/*
 		 * This piece of code only works if the first page is
@@ -81,16 +81,25 @@
 	if (srb->cmnd[0] != INQUIRY)
 		return;
 
-	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
+	/* oddly short buffer -- bail out */
+	if (srb->request_bufflen < 3)
+		return;
 
 	data_ptr = find_data_location(srb);
 
+	/* if it's already 2, bail */
+	if ((data_ptr[2] & 7) == 2)
+		return;
+
+	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n",
+		data_ptr[2] & 7);
+
 	/* Change the SCSI revision number */
 	data_ptr[2] = (data_ptr[2] & ~7) | 2;
 }
 
 /*
- * Fix-up the return data from a READ CAPACITY command. My Feiya reader
+ * Fix-up the return data from a READ CAPACITY command. A Feiya reader
  * returns a value that is 1 too large.
  */
 static void fix_read_capacity(Scsi_Cmnd *srb)
@@ -106,7 +115,7 @@
 
 	capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]);
 	US_DEBUGP("US: Fixing capacity: from %ld to %ld\n",
-	       capacity+1, capacity);
+		capacity+1, capacity);
 	capacity--;
 	dp[0] = (capacity >> 24);
 	dp[1] = (capacity >> 16);
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	Mon Jul 14 14:27:19 2003
+++ b/drivers/usb/storage/usb.h	Mon Jul 14 14:27:19 2003
@@ -102,7 +102,7 @@
 #define US_FL_IGNORE_SER      0x00000010 /* Ignore the serial number given  */
 #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets */
 #define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs fixing */
-#define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big */
+#define US_FL_FIX_CAPACITY    0x00000080 /* READ_CAPACITY response too big */
 
 #define USB_STOR_STRING_LEN 32
 
