[PATCH RESEND] test capacity early in setsize() to avoid bad casts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is just a resend with Andries Brouwer ccd to make sure
I did not mess up any of the disk geometry stuff up.


On 32 bit archs with LBD set, setsize can cast a capacity so
that we result in heads==0 (capacity is sector_t which would
be a 64 bit value with LBD but it gets cast to a unsigned long
which is only 32 bits). Some userspace programs will then blindly
use this heads value to do fun things. This patch avoids the bad
casts by having setsize check for the max value it can support
which is 7905 MB. By returning early when its limit is passed to it
we also avoid bad casts which could result in heads getting set to
zero here.

Patch is made against 2.6.13.rc2 but applies to scsi-misc and scsi-rc
trees.

--- linux-2.6.13-rc2/drivers/scsi/scsicam.c	2005-07-05 22:46:33.000000000 -0500
+++ linux-2.6.13-rc2.work/drivers/scsi/scsicam.c	2005-07-12 16:15:07.000000000 -0500
@@ -21,7 +21,7 @@
 #include <scsi/scsicam.h>
 
 
-static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
+static int setsize(sector_t capacity, unsigned int *cyls, unsigned int *hds,
 		   unsigned int *secs);
 
 unsigned char *scsi_bios_ptable(struct block_device *dev)
@@ -72,7 +72,7 @@ int scsicam_bios_param(struct block_devi
 		/* pick some standard mapping with at most 1024 cylinders,
 		   and at most 62 sectors per track - this works up to
 		   7905 MB */
-		ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
+		ret = setsize(capacity, (unsigned int *)ip + 2,
 		       (unsigned int *)ip + 0, (unsigned int *)ip + 1);
 	}
 
@@ -213,12 +213,21 @@ EXPORT_SYMBOL(scsi_partsize);
  * accommodated. This algorithm does not use physical geometry. 
  */
 
-static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
+static int setsize(sector_t cap, unsigned int *cyls, unsigned int *hds,
 		   unsigned int *secs)
 {
 	unsigned int rv = 0;
-	unsigned long heads, sectors, cylinders, temp;
+	unsigned long heads, sectors, cylinders, temp, capacity;
 
+	/*
+	 * A capacity > 7905 MB (16189440 512 byte sectors) will result
+	 * in heads > 255 and a capacity >> 7905 will result in bad casts
+	 * and possibly heads == 0.
+	 */
+	if (cap > 16189440)
+		return -1;
+
+	capacity = (unsigned long) cap;
 	cylinders = 1024L;	/* Set number of cylinders to max */
 	sectors = 62L;		/* Maximize sectors per track */
 


-
: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux