| From 5682f1121ac35b3a31370a337e534b05b6accea9 Mon Sep 17 00:00:00 2001 |
| From: "Martin K. Petersen" <martin.petersen@oracle.com> |
| Date: Tue, 4 Apr 2017 10:42:30 -0400 |
| Subject: [PATCH] scsi: sd: Fix capacity calculation with 32-bit sector_t |
| |
| commit 7c856152cb92f8eee2df29ef325a1b1f43161aff upstream. |
| |
| We previously made sure that the reported disk capacity was less than |
| 0xffffffff blocks when the kernel was not compiled with large sector_t |
| support (CONFIG_LBDAF). However, this check assumed that the capacity |
| was reported in units of 512 bytes. |
| |
| Add a sanity check function to ensure that we only enable disks if the |
| entire reported capacity can be expressed in terms of sector_t. |
| |
| Cc: <stable@vger.kernel.org> |
| Reported-by: Steve Magnani <steve.magnani@digidescorp.com> |
| Cc: Bart Van Assche <Bart.VanAssche@sandisk.com> |
| Reviewed-by: Bart Van Assche <Bart.VanAssche@sandisk.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c |
| index 3a5208c53e4a..843e4ae24f6a 100644 |
| --- a/drivers/scsi/sd.c |
| +++ b/drivers/scsi/sd.c |
| @@ -2056,6 +2056,22 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, |
| |
| #define READ_CAPACITY_RETRIES_ON_RESET 10 |
| |
| +/* |
| + * Ensure that we don't overflow sector_t when CONFIG_LBDAF is not set |
| + * and the reported logical block size is bigger than 512 bytes. Note |
| + * that last_sector is a u64 and therefore logical_to_sectors() is not |
| + * applicable. |
| + */ |
| +static bool sd_addressable_capacity(u64 lba, unsigned int sector_size) |
| +{ |
| + u64 last_sector = (lba + 1ULL) << (ilog2(sector_size) - 9); |
| + |
| + if (sizeof(sector_t) == 4 && last_sector > U32_MAX) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, |
| unsigned char *buffer) |
| { |
| @@ -2121,7 +2137,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, |
| return -ENODEV; |
| } |
| |
| - if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) { |
| + if (!sd_addressable_capacity(lba, sector_size)) { |
| sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " |
| "kernel compiled with support for large block " |
| "devices.\n"); |
| @@ -2207,7 +2223,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, |
| return sector_size; |
| } |
| |
| - if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { |
| + if (!sd_addressable_capacity(lba, sector_size)) { |
| sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " |
| "kernel compiled with support for large block " |
| "devices.\n"); |
| -- |
| 2.12.0 |
| |