block: ioctl: fix information leak to userland

Structure hd_geometry is copied to userland with 4 padding bytes
between cylinders and start fields uninitialized on 64-bit platforms.
It leads to leaking of contents of kernel stack memory.

Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>

(2.6 commit: a014741c0adfb8fb79952939ca087cf03d272bb9)
[WT: different fix from 2.6 because we could not centralize the ioctl, so
 all affected drivers had to be fixed ]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index b1a2766..e462a3c 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -5457,6 +5457,7 @@
     {
     case HDIO_GETGEO:
       /* Get BIOS Disk Geometry. */
+      memset(&Geometry, 0, sizeof(Geometry));
       UserGeometry = (DiskGeometry_T *) Argument;
       if (UserGeometry == NULL) return -EINVAL;
       if (Controller->FirmwareType == DAC960_V1_Controller)
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 36de0ae..85d98d4 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1489,6 +1489,7 @@
 	case HDIO_GETGEO:
 	{
 		struct hd_geometry loc;
+		memset(&loc, 0, sizeof(loc));
 		loc.heads = unit[drive].type->heads;
 		loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
 		loc.cylinders = unit[drive].type->tracks;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 62b906c..7e83aeb 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -702,6 +702,7 @@
 	   case HDIO_GETGEO:
 	   {
 		struct hd_geometry driver_geo;
+		memset(&driver_geo, 0, sizeof(driver_geo));
 		if (hba[ctlr]->drv[dsk].cylinders) {
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
@@ -718,6 +719,7 @@
 	case HDIO_GETGEO_BIG:
 	{
 		struct hd_big_geometry driver_geo;
+		memset(&driver_geo, 0, sizeof(driver_geo));
 		if (hba[ctlr]->drv[dsk].cylinders) {
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index dfd891f..af8815d 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1247,6 +1247,7 @@
 	{
 		struct hd_geometry driver_geo;
 
+		memset(&driver_geo, 0, sizeof(driver_geo));
 		if (hba[ctlr]->drv[dsk].cylinders) {
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
@@ -1268,6 +1269,7 @@
 	{
 		struct hd_big_geometry driver_geo;
 
+		memset(&driver_geo, 0, sizeof(driver_geo));
 		if (hba[ctlr]->drv[dsk].cylinders) {
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 24b68c0..f96cc3d 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3504,6 +3504,7 @@
 		case HDIO_GETGEO:
 		{
 			struct hd_geometry loc;
+			memset(&loc, 0, sizeof(loc));
 			ECALL(get_floppy_geometry(drive, type, &g));
 			loc.heads = g->head;
 			loc.sectors = g->sect;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index d04f0f0..0780a34 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -477,6 +477,7 @@
 	case HDIO_GETGEO: {
 		struct hd_geometry geom;
 
+		memset(&geom, 0, sizeof(geom));
 		if (!usermem)
 			return -EINVAL;
 
@@ -503,6 +504,7 @@
 	case HDIO_GETGEO_BIG: {
 		struct hd_big_geometry geom;
 
+		memset(&geom, 0, sizeof(geom));
 		if (!usermem)
 			return -EINVAL;
 
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 79954a7..da51c29 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -866,6 +866,7 @@
 		 * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
 		 * whatever cylinders.
 		 */
+		memset(&geo, 0, sizeof(geo));
 		err = ! access_ok(VERIFY_WRITE, arg, sizeof(geo));
 		if (err) return -EFAULT;
 		size = cards[card_number].mm_size * (1024 / MM_HARDSECT);
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 8f72792..c5b27fa 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -330,6 +330,7 @@
 		{
 			struct hd_geometry g;
 			struct hd_geometry *geometry = (struct hd_geometry *) arg;
+			memset(&g, 0, sizeof(g));
 			g.heads = xd_info[dev].heads;
 			g.sectors = xd_info[dev].sectors;
 			g.cylinders = xd_info[dev].cylinders;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 60d092f..1df2dc2 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -637,6 +637,7 @@
 		case HDIO_GETGEO:
 		{
 			struct hd_geometry g; 
+			memset(&g, 0, sizeof(g));
 			if (!loc)  return -EINVAL;
 			g.heads = hd_info[dev].head;
 			g.sectors = hd_info[dev].sect;
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 474130d..d7fa39d 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -1034,6 +1034,7 @@
 		{
 			struct hd_geometry g;
 			int u=minor&0xF0;
+			memset(&g, 0, sizeof(g));
 			i2o_block_biosparam(i2ob_sizes[u]<<1, 
 				&g.cylinders, &g.heads, &g.sectors);
 			g.start = i2ob[minor].start_sect;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 5c7816a..f407820 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -802,6 +802,7 @@
 	case HDIO_GETGEO: {
 		struct hd_geometry g;
 
+		memset(&g, 0, sizeof(g));
 		g.heads = nftl->heads;
 		g.sectors = nftl->sectors;
 		g.cylinders = nftl->cylinders;