Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Kees Cook and committed by
Jens Axboe
704f8392 429296cc

+18 -8
+3 -3
drivers/scsi/scsi_lib.c
··· 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 242 * @sdev: scsi device 243 243 * @cmd: scsi command 244 244 * @data_direction: data direction ··· 255 255 * Returns the scsi_cmnd result field if a command was executed, or a negative 256 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 259 int data_direction, void *buffer, unsigned bufflen, 260 260 unsigned char *sense, struct scsi_sense_hdr *sshdr, 261 261 int timeout, int retries, u64 flags, req_flags_t rq_flags, ··· 309 309 310 310 return ret; 311 311 } 312 - EXPORT_SYMBOL(scsi_execute); 312 + EXPORT_SYMBOL(__scsi_execute); 313 313 314 314 /* 315 315 * Function: scsi_init_cmd_errh()
+2 -4
include/scsi/scsi_cmnd.h
··· 15 15 struct Scsi_Host; 16 16 struct scsi_driver; 17 17 18 - #include <scsi/scsi_device.h> 19 - 20 18 /* 21 19 * MAX_COMMAND_SIZE is: 22 20 * The longest fixed-length SCSI CDB as per the SCSI standard. ··· 119 121 struct request *request; /* The command we are 120 122 working on */ 121 123 122 - #define SCSI_SENSE_BUFFERSIZE 96 123 124 unsigned char *sense_buffer; 124 125 /* obtained by REQUEST SENSE when 125 126 * CHECK CONDITION is received on original 126 - * command (auto-sense) */ 127 + * command (auto-sense). Length must be 128 + * SCSI_SENSE_BUFFERSIZE bytes. */ 127 129 128 130 /* Low-level done function - can be used by low-level driver to point 129 131 * to completion function. Not used by mid/upper level code. */
+13 -1
include/scsi/scsi_device.h
··· 17 17 18 18 typedef __u64 __bitwise blist_flags_t; 19 19 20 + #define SCSI_SENSE_BUFFERSIZE 96 21 + 20 22 struct scsi_mode_data { 21 23 __u32 length; 22 24 __u16 block_descriptor_length; ··· 428 426 extern int scsi_is_sdev_device(const struct device *); 429 427 extern int scsi_is_target_device(const struct device *); 430 428 extern void scsi_sanitize_inquiry_string(unsigned char *s, int len); 431 - extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, 429 + extern int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, 432 430 int data_direction, void *buffer, unsigned bufflen, 433 431 unsigned char *sense, struct scsi_sense_hdr *sshdr, 434 432 int timeout, int retries, u64 flags, 435 433 req_flags_t rq_flags, int *resid); 434 + /* Make sure any sense buffer is the correct size. */ 435 + #define scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, \ 436 + sshdr, timeout, retries, flags, rq_flags, resid) \ 437 + ({ \ 438 + BUILD_BUG_ON((sense) != NULL && \ 439 + sizeof(sense) != SCSI_SENSE_BUFFERSIZE); \ 440 + __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, \ 441 + sense, sshdr, timeout, retries, flags, rq_flags, \ 442 + resid); \ 443 + }) 436 444 static inline int scsi_execute_req(struct scsi_device *sdev, 437 445 const unsigned char *cmd, int data_direction, void *buffer, 438 446 unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,