diff options
author | brking@us.ibm.com <brking@us.ibm.com> | 2006-01-23 16:03:22 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2006-01-26 15:13:50 -0500 |
commit | bb1d1073a10fdc8547e3eb821ee2488260094b39 (patch) | |
tree | 139a30834cea40e0d967506cfdaea603cf56a192 | |
parent | 15084a4a63bc300c18b28a8a9afac870c552abce (diff) |
[SCSI] Prevent scsi_execute_async from guessing cdb length
When the scsi_execute_async interface was added it ended up reducing
the flexibility of userspace to send arbitrary scsi commands through
sg using SG_IO. The SG_IO interface allows userspace to specify the
CDB length. This is now ignored in scsi_execute_async and it is
guessed using the COMMAND_SIZE macro, which is not always correct,
particularly for vendor specific commands. This patch adds a cmd_len
parameter to the scsi_execute_async interface to allow the caller
to specify the length of the CDB.
Signed-off-by: Brian King <brking@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/scsi_error.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 5 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/st.c | 2 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 2 |
5 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a2333d2c7af..5cc97b72166 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) | |||
1350 | cmnd[4] = SCSI_REMOVAL_PREVENT; | 1350 | cmnd[4] = SCSI_REMOVAL_PREVENT; |
1351 | cmnd[5] = 0; | 1351 | cmnd[5] = 0; |
1352 | 1352 | ||
1353 | scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ, | 1353 | scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ, |
1354 | 5, NULL, NULL, GFP_KERNEL); | 1354 | 5, NULL, NULL, GFP_KERNEL); |
1355 | } | 1355 | } |
1356 | 1356 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3574ba935af..4a602853a98 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -436,6 +436,7 @@ free_bios: | |||
436 | * scsi_execute_async - insert request | 436 | * scsi_execute_async - insert request |
437 | * @sdev: scsi device | 437 | * @sdev: scsi device |
438 | * @cmd: scsi command | 438 | * @cmd: scsi command |
439 | * @cmd_len: length of scsi cdb | ||
439 | * @data_direction: data direction | 440 | * @data_direction: data direction |
440 | * @buffer: data buffer (this can be a kernel buffer or scatterlist) | 441 | * @buffer: data buffer (this can be a kernel buffer or scatterlist) |
441 | * @bufflen: len of buffer | 442 | * @bufflen: len of buffer |
@@ -445,7 +446,7 @@ free_bios: | |||
445 | * @flags: or into request flags | 446 | * @flags: or into request flags |
446 | **/ | 447 | **/ |
447 | int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, | 448 | int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, |
448 | int data_direction, void *buffer, unsigned bufflen, | 449 | int cmd_len, int data_direction, void *buffer, unsigned bufflen, |
449 | int use_sg, int timeout, int retries, void *privdata, | 450 | int use_sg, int timeout, int retries, void *privdata, |
450 | void (*done)(void *, char *, int, int), gfp_t gfp) | 451 | void (*done)(void *, char *, int, int), gfp_t gfp) |
451 | { | 452 | { |
@@ -472,7 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, | |||
472 | if (err) | 473 | if (err) |
473 | goto free_req; | 474 | goto free_req; |
474 | 475 | ||
475 | req->cmd_len = COMMAND_SIZE(cmd[0]); | 476 | req->cmd_len = cmd_len; |
476 | memcpy(req->cmd, cmd, req->cmd_len); | 477 | memcpy(req->cmd, cmd, req->cmd_len); |
477 | req->sense = sioc->sense; | 478 | req->sense = sioc->sense; |
478 | req->sense_len = 0; | 479 | req->sense_len = 0; |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 78aad9582bc..7d0700091f3 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, | |||
741 | hp->duration = jiffies_to_msecs(jiffies); | 741 | hp->duration = jiffies_to_msecs(jiffies); |
742 | /* Now send everything of to mid-level. The next time we hear about this | 742 | /* Now send everything of to mid-level. The next time we hear about this |
743 | packet is when sg_cmd_done() is called (i.e. a callback). */ | 743 | packet is when sg_cmd_done() is called (i.e. a callback). */ |
744 | if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer, | 744 | if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, |
745 | hp->dxfer_len, srp->data.k_use_sg, timeout, | 745 | hp->dxfer_len, srp->data.k_use_sg, timeout, |
746 | SG_DEFAULT_RETRIES, srp, sg_cmd_done, | 746 | SG_DEFAULT_RETRIES, srp, sg_cmd_done, |
747 | GFP_ATOMIC)) { | 747 | GFP_ATOMIC)) { |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 13b1d3aac26..7f96f33c1bb 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -508,7 +508,7 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd | |||
508 | STp->buffer->cmdstat.have_sense = 0; | 508 | STp->buffer->cmdstat.have_sense = 0; |
509 | STp->buffer->syscall_result = 0; | 509 | STp->buffer->syscall_result = 0; |
510 | 510 | ||
511 | if (scsi_execute_async(STp->device, cmd, direction, | 511 | if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, |
512 | &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, | 512 | &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, |
513 | timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { | 513 | timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { |
514 | /* could not allocate the buffer or request was too large */ | 514 | /* could not allocate the buffer or request was too large */ |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index e94ca4d3603..290e3b4d2ae 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
275 | int data_direction, void *buffer, unsigned bufflen, | 275 | int data_direction, void *buffer, unsigned bufflen, |
276 | struct scsi_sense_hdr *, int timeout, int retries); | 276 | struct scsi_sense_hdr *, int timeout, int retries); |
277 | extern int scsi_execute_async(struct scsi_device *sdev, | 277 | extern int scsi_execute_async(struct scsi_device *sdev, |
278 | const unsigned char *cmd, int data_direction, | 278 | const unsigned char *cmd, int cmd_len, int data_direction, |
279 | void *buffer, unsigned bufflen, int use_sg, | 279 | void *buffer, unsigned bufflen, int use_sg, |
280 | int timeout, int retries, void *privdata, | 280 | int timeout, int retries, void *privdata, |
281 | void (*done)(void *, char *, int, int), | 281 | void (*done)(void *, char *, int, int), |