diff options
| author | Sagi Grimberg <sagig@mellanox.com> | 2015-07-15 03:55:37 -0400 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-07-24 01:53:05 -0400 |
| commit | f5a8b3a796db01b639435515b3adc003b9f27387 (patch) | |
| tree | 3ff4e026ec2af94cbef2cef9d365a5faf141059c /drivers/scsi | |
| parent | 12306b425d0dbab7b60f54e02d67cf3dfae494d1 (diff) | |
scsi: Protect against buffer possible overflow in scsi_set_sense_information
Make sure that the input sense buffer has sufficient length
to fit the information descriptor (12 additional bytes).
Modify scsi_set_sense_information to receive the sense buffer
length and adjust its callers scsi target and libata.
(Fix patch fuzz in scsi_set_sense_information - nab)
Reported-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Tejun Heo <tj@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/scsi_common.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index ee6bdf43a8ea..c126966130ab 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/bug.h> | 5 | #include <linux/bug.h> |
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
| 8 | #include <linux/errno.h> | ||
| 8 | #include <asm/unaligned.h> | 9 | #include <asm/unaligned.h> |
| 9 | #include <scsi/scsi_common.h> | 10 | #include <scsi/scsi_common.h> |
| 10 | 11 | ||
| @@ -249,10 +250,13 @@ EXPORT_SYMBOL(scsi_build_sense_buffer); | |||
| 249 | * scsi_set_sense_information - set the information field in a | 250 | * scsi_set_sense_information - set the information field in a |
| 250 | * formatted sense data buffer | 251 | * formatted sense data buffer |
| 251 | * @buf: Where to build sense data | 252 | * @buf: Where to build sense data |
| 253 | * @buf_len: buffer length | ||
| 252 | * @info: 64-bit information value to be set | 254 | * @info: 64-bit information value to be set |
| 253 | * | 255 | * |
| 256 | * Return value: | ||
| 257 | * 0 on success or EINVAL for invalid sense buffer length | ||
| 254 | **/ | 258 | **/ |
| 255 | void scsi_set_sense_information(u8 *buf, u64 info) | 259 | int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) |
| 256 | { | 260 | { |
| 257 | if ((buf[0] & 0x7f) == 0x72) { | 261 | if ((buf[0] & 0x7f) == 0x72) { |
| 258 | u8 *ucp, len; | 262 | u8 *ucp, len; |
| @@ -263,6 +267,11 @@ void scsi_set_sense_information(u8 *buf, u64 info) | |||
| 263 | buf[7] = len + 0xc; | 267 | buf[7] = len + 0xc; |
| 264 | ucp = buf + 8 + len; | 268 | ucp = buf + 8 + len; |
| 265 | } | 269 | } |
| 270 | |||
| 271 | if (buf_len < len + 0xc) | ||
| 272 | /* Not enough room for info */ | ||
| 273 | return -EINVAL; | ||
| 274 | |||
| 266 | ucp[0] = 0; | 275 | ucp[0] = 0; |
| 267 | ucp[1] = 0xa; | 276 | ucp[1] = 0xa; |
| 268 | ucp[2] = 0x80; /* Valid bit */ | 277 | ucp[2] = 0x80; /* Valid bit */ |
| @@ -272,5 +281,7 @@ void scsi_set_sense_information(u8 *buf, u64 info) | |||
| 272 | buf[0] |= 0x80; | 281 | buf[0] |= 0x80; |
| 273 | put_unaligned_be64(info, &buf[3]); | 282 | put_unaligned_be64(info, &buf[3]); |
| 274 | } | 283 | } |
| 284 | |||
| 285 | return 0; | ||
| 275 | } | 286 | } |
| 276 | EXPORT_SYMBOL(scsi_set_sense_information); | 287 | EXPORT_SYMBOL(scsi_set_sense_information); |
