From bb1d1073a10fdc8547e3eb821ee2488260094b39 Mon Sep 17 00:00:00 2001 From: "brking@us.ibm.com" Date: Mon, 23 Jan 2006 15:03:22 -0600 Subject: [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 Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 2 +- drivers/scsi/scsi_lib.c | 5 +++-- drivers/scsi/sg.c | 2 +- drivers/scsi/st.c | 2 +- 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) cmnd[4] = SCSI_REMOVAL_PREVENT; cmnd[5] = 0; - scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ, + scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ, 5, NULL, NULL, GFP_KERNEL); } 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: * scsi_execute_async - insert request * @sdev: scsi device * @cmd: scsi command + * @cmd_len: length of scsi cdb * @data_direction: data direction * @buffer: data buffer (this can be a kernel buffer or scatterlist) * @bufflen: len of buffer @@ -445,7 +446,7 @@ free_bios: * @flags: or into request flags **/ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, - int data_direction, void *buffer, unsigned bufflen, + int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, int timeout, int retries, void *privdata, void (*done)(void *, char *, int, int), gfp_t gfp) { @@ -472,7 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, if (err) goto free_req; - req->cmd_len = COMMAND_SIZE(cmd[0]); + req->cmd_len = cmd_len; memcpy(req->cmd, cmd, req->cmd_len); req->sense = sioc->sense; 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, hp->duration = jiffies_to_msecs(jiffies); /* Now send everything of to mid-level. The next time we hear about this packet is when sg_cmd_done() is called (i.e. a callback). */ - if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer, + if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, hp->dxfer_len, srp->data.k_use_sg, timeout, SG_DEFAULT_RETRIES, srp, sg_cmd_done, 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 STp->buffer->cmdstat.have_sense = 0; STp->buffer->syscall_result = 0; - if (scsi_execute_async(STp->device, cmd, direction, + if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { /* 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, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *, int timeout, int retries); extern int scsi_execute_async(struct scsi_device *sdev, - const unsigned char *cmd, int data_direction, + const unsigned char *cmd, int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, int timeout, int retries, void *privdata, void (*done)(void *, char *, int, int), -- cgit v1.2.3