Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 526f7c79 authored by Martin K. Petersen's avatar Martin K. Petersen Committed by James Bottomley
Browse files

[SCSI] sd: Fix overflow with big physical blocks



The hw_sector_size variable could overflow if a device reported huge
physical blocks.  Switch to the more accurate physical_block_size
terminology and make sure we use an unsigned int to match the range
permitted by READ CAPACITY(16).

Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 3e51d3c9
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -1554,7 +1554,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
	}

	/* Logical blocks per physical block exponent */
	sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size;
	sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size;

	/* Lowest aligned logical block */
	alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
@@ -1567,7 +1567,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
		struct request_queue *q = sdp->request_queue;

		sdkp->thin_provisioning = 1;
		q->limits.discard_granularity = sdkp->hw_sector_size;
		q->limits.discard_granularity = sdkp->physical_block_size;
		q->limits.max_discard_sectors = 0xffffffff;

		if (buffer[14] & 0x40) /* TPRZ */
@@ -1635,7 +1635,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
	}

	sdkp->capacity = lba + 1;
	sdkp->hw_sector_size = sector_size;
	sdkp->physical_block_size = sector_size;
	return sector_size;
}

@@ -1756,10 +1756,10 @@ got_data:
				  (unsigned long long)sdkp->capacity,
				  sector_size, cap_str_10, cap_str_2);

			if (sdkp->hw_sector_size != sector_size)
			if (sdkp->physical_block_size != sector_size)
				sd_printk(KERN_NOTICE, sdkp,
					  "%u-byte physical blocks\n",
					  sdkp->hw_sector_size);
					  sdkp->physical_block_size);
		}
	}

@@ -1773,7 +1773,8 @@ got_data:
	else if (sector_size == 256)
		sdkp->capacity >>= 1;

	blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size);
	blk_queue_physical_block_size(sdp->request_queue,
				      sdkp->physical_block_size);
	sdkp->device->sector_size = sector_size;
}

+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ struct scsi_disk {
	atomic_t	openers;
	sector_t	capacity;	/* size in 512-byte sectors */
	u32		index;
	unsigned short	hw_sector_size;
	unsigned int	physical_block_size;
	u8		media_present;
	u8		write_prot;
	u8		protection_type;/* Data Integrity Field */