aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <error27@gmail.com>2010-10-08 03:03:07 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-10-25 16:01:14 -0400
commitf63ae56e4e97fb12053590e41a4fa59e7daa74a4 (patch)
treee5087c68ff1c9387a8bed84e4b2ab30d19e02852
parent546ae796bfac6399e30da4b5af2cf7a6d0f8a4ec (diff)
[SCSI] gdth: integer overflow in ioctl
gdth_ioctl_alloc() takes the size variable as an int. copy_from_user() takes the size variable as an unsigned long. gen.data_len and gen.sense_len are unsigned longs. On x86_64 longs are 64 bit and ints are 32 bit. We could pass in a very large number and the allocation would truncate the size to 32 bits and allocate a small buffer. Then when we do the copy_from_user(), it would result in a memory corruption. CC: stable@kernel.org Signed-off-by: Dan Carpenter <error27@gmail.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/gdth.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 5a3f93101017..841101846b88 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4177,6 +4177,14 @@ static int ioc_general(void __user *arg, char *cmnd)
4177 ha = gdth_find_ha(gen.ionode); 4177 ha = gdth_find_ha(gen.ionode);
4178 if (!ha) 4178 if (!ha)
4179 return -EFAULT; 4179 return -EFAULT;
4180
4181 if (gen.data_len > INT_MAX)
4182 return -EINVAL;
4183 if (gen.sense_len > INT_MAX)
4184 return -EINVAL;
4185 if (gen.data_len + gen.sense_len > INT_MAX)
4186 return -EINVAL;
4187
4180 if (gen.data_len + gen.sense_len != 0) { 4188 if (gen.data_len + gen.sense_len != 0) {
4181 if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, 4189 if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len,
4182 FALSE, &paddr))) 4190 FALSE, &paddr)))