summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_common.c
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2015-07-15 10:55:37 +0300
committerNicholas Bellinger <nab@linux-iscsi.org>2015-07-23 22:53:05 -0700
commitf5a8b3a796db01b639435515b3adc003b9f27387 (patch)
tree3ff4e026ec2af94cbef2cef9d365a5faf141059c /drivers/scsi/scsi_common.c
parent12306b425d0dbab7b60f54e02d67cf3dfae494d1 (diff)
downloadlwn-f5a8b3a796db01b639435515b3adc003b9f27387.tar.gz
lwn-f5a8b3a796db01b639435515b3adc003b9f27387.zip
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.c13
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);