diff options
author | Kees Cook <keescook@chromium.org> | 2018-07-31 15:51:54 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-08-02 17:23:51 -0400 |
commit | 704f83928c8e7da6e06144569efb15dec73278e8 (patch) | |
tree | 6603bc65758e0c761fc773b8341bf9875dc5fe76 | |
parent | 429296cc51c4cf145b240a78c8d68545e4d67e4c (diff) |
scsi: Check sense buffer size at build time
To avoid introducing problems like those fixed in commit f7068114d45e
("sr: pass down correctly sized SCSI sense buffer"), this creates a macro
wrapper for scsi_execute() that verifies the size of the sense buffer
similar to what was done for command string sizes in commit 3756f6401c30
("exec: avoid gcc-8 warning for get_task_comm").
Another solution could be to add a length argument to scsi_execute(),
but this function already takes a lot of arguments and Jens was not fond
of that approach.
Additionally, this moves the SCSI_SENSE_BUFFERSIZE definition into
scsi_device.h, and removes a redundant include for scsi_device.h from
scsi_cmnd.h.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/scsi/scsi_lib.c | 6 | ||||
-rw-r--r-- | include/scsi/scsi_cmnd.h | 6 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 14 |
3 files changed, 18 insertions, 8 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 41e9ac9fc138..9cb9a166fa0c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -238,7 +238,7 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | |||
238 | 238 | ||
239 | 239 | ||
240 | /** | 240 | /** |
241 | * scsi_execute - insert request and wait for the result | 241 | * __scsi_execute - insert request and wait for the result |
242 | * @sdev: scsi device | 242 | * @sdev: scsi device |
243 | * @cmd: scsi command | 243 | * @cmd: scsi command |
244 | * @data_direction: data direction | 244 | * @data_direction: data direction |
@@ -255,7 +255,7 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | |||
255 | * Returns the scsi_cmnd result field if a command was executed, or a negative | 255 | * Returns the scsi_cmnd result field if a command was executed, or a negative |
256 | * Linux error code if we didn't get that far. | 256 | * Linux error code if we didn't get that far. |
257 | */ | 257 | */ |
258 | int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | 258 | int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, |
259 | int data_direction, void *buffer, unsigned bufflen, | 259 | int data_direction, void *buffer, unsigned bufflen, |
260 | unsigned char *sense, struct scsi_sense_hdr *sshdr, | 260 | unsigned char *sense, struct scsi_sense_hdr *sshdr, |
261 | int timeout, int retries, u64 flags, req_flags_t rq_flags, | 261 | int timeout, int retries, u64 flags, req_flags_t rq_flags, |
@@ -309,7 +309,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
309 | 309 | ||
310 | return ret; | 310 | return ret; |
311 | } | 311 | } |
312 | EXPORT_SYMBOL(scsi_execute); | 312 | EXPORT_SYMBOL(__scsi_execute); |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * Function: scsi_init_cmd_errh() | 315 | * Function: scsi_init_cmd_errh() |
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index cae229b5395c..c891ada3c5c2 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h | |||
@@ -15,8 +15,6 @@ | |||
15 | struct Scsi_Host; | 15 | struct Scsi_Host; |
16 | struct scsi_driver; | 16 | struct scsi_driver; |
17 | 17 | ||
18 | #include <scsi/scsi_device.h> | ||
19 | |||
20 | /* | 18 | /* |
21 | * MAX_COMMAND_SIZE is: | 19 | * MAX_COMMAND_SIZE is: |
22 | * The longest fixed-length SCSI CDB as per the SCSI standard. | 20 | * The longest fixed-length SCSI CDB as per the SCSI standard. |
@@ -121,11 +119,11 @@ struct scsi_cmnd { | |||
121 | struct request *request; /* The command we are | 119 | struct request *request; /* The command we are |
122 | working on */ | 120 | working on */ |
123 | 121 | ||
124 | #define SCSI_SENSE_BUFFERSIZE 96 | ||
125 | unsigned char *sense_buffer; | 122 | unsigned char *sense_buffer; |
126 | /* obtained by REQUEST SENSE when | 123 | /* obtained by REQUEST SENSE when |
127 | * CHECK CONDITION is received on original | 124 | * CHECK CONDITION is received on original |
128 | * command (auto-sense) */ | 125 | * command (auto-sense). Length must be |
126 | * SCSI_SENSE_BUFFERSIZE bytes. */ | ||
129 | 127 | ||
130 | /* Low-level done function - can be used by low-level driver to point | 128 | /* Low-level done function - can be used by low-level driver to point |
131 | * to completion function. Not used by mid/upper level code. */ | 129 | * to completion function. Not used by mid/upper level code. */ |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 4c36af6edd79..202f4d6a4342 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -17,6 +17,8 @@ struct scsi_sense_hdr; | |||
17 | 17 | ||
18 | typedef __u64 __bitwise blist_flags_t; | 18 | typedef __u64 __bitwise blist_flags_t; |
19 | 19 | ||
20 | #define SCSI_SENSE_BUFFERSIZE 96 | ||
21 | |||
20 | struct scsi_mode_data { | 22 | struct scsi_mode_data { |
21 | __u32 length; | 23 | __u32 length; |
22 | __u16 block_descriptor_length; | 24 | __u16 block_descriptor_length; |
@@ -426,11 +428,21 @@ extern const char *scsi_device_state_name(enum scsi_device_state); | |||
426 | extern int scsi_is_sdev_device(const struct device *); | 428 | extern int scsi_is_sdev_device(const struct device *); |
427 | extern int scsi_is_target_device(const struct device *); | 429 | extern int scsi_is_target_device(const struct device *); |
428 | extern void scsi_sanitize_inquiry_string(unsigned char *s, int len); | 430 | extern void scsi_sanitize_inquiry_string(unsigned char *s, int len); |
429 | extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | 431 | extern int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, |
430 | int data_direction, void *buffer, unsigned bufflen, | 432 | int data_direction, void *buffer, unsigned bufflen, |
431 | unsigned char *sense, struct scsi_sense_hdr *sshdr, | 433 | unsigned char *sense, struct scsi_sense_hdr *sshdr, |
432 | int timeout, int retries, u64 flags, | 434 | int timeout, int retries, u64 flags, |
433 | req_flags_t rq_flags, int *resid); | 435 | req_flags_t rq_flags, int *resid); |
436 | /* Make sure any sense buffer is the correct size. */ | ||
437 | #define scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, \ | ||
438 | sshdr, timeout, retries, flags, rq_flags, resid) \ | ||
439 | ({ \ | ||
440 | BUILD_BUG_ON((sense) != NULL && \ | ||
441 | sizeof(sense) != SCSI_SENSE_BUFFERSIZE); \ | ||
442 | __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, \ | ||
443 | sense, sshdr, timeout, retries, flags, rq_flags, \ | ||
444 | resid); \ | ||
445 | }) | ||
434 | static inline int scsi_execute_req(struct scsi_device *sdev, | 446 | static inline int scsi_execute_req(struct scsi_device *sdev, |
435 | const unsigned char *cmd, int data_direction, void *buffer, | 447 | const unsigned char *cmd, int data_direction, void *buffer, |
436 | unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, | 448 | unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, |