|
|
@@ -1803,6 +1803,21 @@ nothing_to_do:
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
|
|
|
+{
|
|
|
+ struct request *rq = scmd->request;
|
|
|
+ u32 req_blocks;
|
|
|
+
|
|
|
+ if (!blk_rq_is_passthrough(rq))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
|
|
|
+ if (n_blocks > req_blocks)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
|
|
|
* @qc: Storage for translated ATA taskfile
|
|
|
@@ -1847,6 +1862,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
|
|
|
scsi_10_lba_len(cdb, &block, &n_block);
|
|
|
if (cdb[1] & (1 << 3))
|
|
|
tf_flags |= ATA_TFLAG_FUA;
|
|
|
+ if (!ata_check_nblocks(scmd, n_block))
|
|
|
+ goto invalid_fld;
|
|
|
break;
|
|
|
case READ_6:
|
|
|
case WRITE_6:
|
|
|
@@ -1861,6 +1878,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
|
|
|
*/
|
|
|
if (!n_block)
|
|
|
n_block = 256;
|
|
|
+ if (!ata_check_nblocks(scmd, n_block))
|
|
|
+ goto invalid_fld;
|
|
|
break;
|
|
|
case READ_16:
|
|
|
case WRITE_16:
|
|
|
@@ -1871,6 +1890,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
|
|
|
scsi_16_lba_len(cdb, &block, &n_block);
|
|
|
if (cdb[1] & (1 << 3))
|
|
|
tf_flags |= ATA_TFLAG_FUA;
|
|
|
+ if (!ata_check_nblocks(scmd, n_block))
|
|
|
+ goto invalid_fld;
|
|
|
break;
|
|
|
default:
|
|
|
DPRINTK("no-byte command\n");
|