Commit bb1d1073 authored by brking@us.ibm.com's avatar brking@us.ibm.com Committed by James Bottomley

[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: default avatarBrian King <brking@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 15084a4a
...@@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) ...@@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
cmnd[4] = SCSI_REMOVAL_PREVENT; cmnd[4] = SCSI_REMOVAL_PREVENT;
cmnd[5] = 0; 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); 5, NULL, NULL, GFP_KERNEL);
} }
......
...@@ -436,6 +436,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, ...@@ -436,6 +436,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
* scsi_execute_async - insert request * scsi_execute_async - insert request
* @sdev: scsi device * @sdev: scsi device
* @cmd: scsi command * @cmd: scsi command
* @cmd_len: length of scsi cdb
* @data_direction: data direction * @data_direction: data direction
* @buffer: data buffer (this can be a kernel buffer or scatterlist) * @buffer: data buffer (this can be a kernel buffer or scatterlist)
* @bufflen: len of buffer * @bufflen: len of buffer
...@@ -445,7 +446,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, ...@@ -445,7 +446,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
* @flags: or into request flags * @flags: or into request flags
**/ **/
int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, 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, int use_sg, int timeout, int retries, void *privdata,
void (*done)(void *, char *, int, int), gfp_t gfp) 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, ...@@ -472,7 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
if (err) if (err)
goto free_req; goto free_req;
req->cmd_len = COMMAND_SIZE(cmd[0]); req->cmd_len = cmd_len;
memcpy(req->cmd, cmd, req->cmd_len); memcpy(req->cmd, cmd, req->cmd_len);
req->sense = sioc->sense; req->sense = sioc->sense;
req->sense_len = 0; req->sense_len = 0;
......
...@@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, ...@@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
hp->duration = jiffies_to_msecs(jiffies); hp->duration = jiffies_to_msecs(jiffies);
/* Now send everything of to mid-level. The next time we hear about this /* 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). */ 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, hp->dxfer_len, srp->data.k_use_sg, timeout,
SG_DEFAULT_RETRIES, srp, sg_cmd_done, SG_DEFAULT_RETRIES, srp, sg_cmd_done,
GFP_ATOMIC)) { GFP_ATOMIC)) {
......
...@@ -508,7 +508,7 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd ...@@ -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->cmdstat.have_sense = 0;
STp->buffer->syscall_result = 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, &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
/* could not allocate the buffer or request was too large */ /* could not allocate the buffer or request was too large */
......
...@@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, ...@@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen, int data_direction, void *buffer, unsigned bufflen,
struct scsi_sense_hdr *, int timeout, int retries); struct scsi_sense_hdr *, int timeout, int retries);
extern int scsi_execute_async(struct scsi_device *sdev, 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, void *buffer, unsigned bufflen, int use_sg,
int timeout, int retries, void *privdata, int timeout, int retries, void *privdata,
void (*done)(void *, char *, int, int), void (*done)(void *, char *, int, int),
......
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