diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2015-07-15 10:55:37 +0300 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-07-23 22:53:05 -0700 |
commit | f5a8b3a796db01b639435515b3adc003b9f27387 (patch) | |
tree | 3ff4e026ec2af94cbef2cef9d365a5faf141059c /drivers/scsi/scsi_common.c | |
parent | 12306b425d0dbab7b60f54e02d67cf3dfae494d1 (diff) | |
download | linux-f5a8b3a796db01b639435515b3adc003b9f27387.tar.bz2 |
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/scsi_common.c')
-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 @@ #include <linux/bug.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/errno.h> #include <asm/unaligned.h> #include <scsi/scsi_common.h> @@ -249,10 +250,13 @@ EXPORT_SYMBOL(scsi_build_sense_buffer); * scsi_set_sense_information - set the information field in a * formatted sense data buffer * @buf: Where to build sense data + * @buf_len: buffer length * @info: 64-bit information value to be set * + * Return value: + * 0 on success or EINVAL for invalid sense buffer length **/ -void scsi_set_sense_information(u8 *buf, u64 info) +int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) { if ((buf[0] & 0x7f) == 0x72) { u8 *ucp, len; @@ -263,6 +267,11 @@ void scsi_set_sense_information(u8 *buf, u64 info) buf[7] = len + 0xc; ucp = buf + 8 + len; } + + if (buf_len < len + 0xc) + /* Not enough room for info */ + return -EINVAL; + ucp[0] = 0; ucp[1] = 0xa; ucp[2] = 0x80; /* Valid bit */ @@ -272,5 +281,7 @@ void scsi_set_sense_information(u8 *buf, u64 info) buf[0] |= 0x80; put_unaligned_be64(info, &buf[3]); } + + return 0; } EXPORT_SYMBOL(scsi_set_sense_information); |