Commit 1110636e authored by Damien Le Moal's avatar Damien Le Moal Committed by Greg Kroah-Hartman

scsi: sd_zbc: Fix potential memory leak

commit 4b433924 upstream.

Rework sd_zbc_check_zone_size() to avoid a memory leak due to an early
return if sd_zbc_report_zones() fails.
Reported-by: default avatarDavid.butterfield <david.butterfield@wdc.com>
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarBart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2c6025eb
...@@ -425,7 +425,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, ...@@ -425,7 +425,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp,
static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
{ {
u64 zone_blocks; u64 zone_blocks = 0;
sector_t block = 0; sector_t block = 0;
unsigned char *buf; unsigned char *buf;
unsigned char *rec; unsigned char *rec;
...@@ -443,10 +443,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -443,10 +443,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
/* Do a report zone to get the same field */ /* Do a report zone to get the same field */
ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0); ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0);
if (ret) { if (ret)
zone_blocks = 0; goto out_free;
goto out;
}
same = buf[4] & 0x0f; same = buf[4] & 0x0f;
if (same > 0) { if (same > 0) {
...@@ -489,7 +487,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -489,7 +487,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
ret = sd_zbc_report_zones(sdkp, buf, ret = sd_zbc_report_zones(sdkp, buf,
SD_ZBC_BUF_SIZE, block); SD_ZBC_BUF_SIZE, block);
if (ret) if (ret)
return ret; goto out_free;
} }
} while (block < sdkp->capacity); } while (block < sdkp->capacity);
...@@ -497,34 +495,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ...@@ -497,34 +495,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
zone_blocks = sdkp->zone_blocks; zone_blocks = sdkp->zone_blocks;
out: out:
kfree(buf);
if (!zone_blocks) { if (!zone_blocks) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Devices with non constant zone " "Devices with non constant zone "
"size are not supported\n"); "size are not supported\n");
return -ENODEV; ret = -ENODEV;
} } else if (!is_power_of_2(zone_blocks)) {
if (!is_power_of_2(zone_blocks)) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Devices with non power of 2 zone " "Devices with non power of 2 zone "
"size are not supported\n"); "size are not supported\n");
return -ENODEV; ret = -ENODEV;
} } else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
if (sdkp->first_scan) if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"Zone size too large\n"); "Zone size too large\n");
return -ENODEV; ret = -ENODEV;
} else {
sdkp->zone_blocks = zone_blocks;
sdkp->zone_shift = ilog2(zone_blocks);
} }
sdkp->zone_blocks = zone_blocks; out_free:
kfree(buf);
return 0; return ret;
} }
static int sd_zbc_setup(struct scsi_disk *sdkp) static int sd_zbc_setup(struct scsi_disk *sdkp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment