[PATCH AUTOSEL for 4.4 023/162] scsi: csiostor: Avoid content leaks and casts

2018-04-08 Thread Sasha Levin
From: Kees Cook 

[ Upstream commit 42c335f7e67029d2e01711f2f2bc6252277c8993 ]

When copying attributes, the len argument was padded out and the
resulting memcpy() would copy beyond the end of the source buffer.
Avoid this, and use size_t for val_len to avoid all the casts.
Similarly, avoid source buffer casts and use void *.

Additionally enforces val_len can be represented by u16 and that the DMA
buffer was not overflowed. Fixes the size of mfa, which is not
FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN (but it will be padded up to 4). This
was noticed by the future CONFIG_FORTIFY_SOURCE checks.

Cc: Daniel Micay 
Signed-off-by: Kees Cook 
Acked-by: Varun Prakash 
Signed-off-by: Martin K. Petersen 
Signed-off-by: Sasha Levin 
---
 drivers/scsi/csiostor/csio_lnode.c | 43 +++---
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/csiostor/csio_lnode.c 
b/drivers/scsi/csiostor/csio_lnode.c
index c00b2ff72b55..be5ee2d37815 100644
--- a/drivers/scsi/csiostor/csio_lnode.c
+++ b/drivers/scsi/csiostor/csio_lnode.c
@@ -238,14 +238,23 @@ csio_osname(uint8_t *buf, size_t buf_len)
 }
 
 static inline void
-csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len)
+csio_append_attrib(uint8_t **ptr, uint16_t type, void *val, size_t val_len)
 {
+   uint16_t len;
struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr;
+
+   if (WARN_ON(val_len > U16_MAX))
+   return;
+
+   len = val_len;
+
ae->type = htons(type);
len += 4;   /* includes attribute type and length */
len = (len + 3) & ~3;   /* should be multiple of 4 bytes */
ae->len = htons(len);
-   memcpy(ae->value, val, len);
+   memcpy(ae->value, val, val_len);
+   if (len > val_len)
+   memset(ae->value + val_len, 0, len - val_len);
*ptr += len;
 }
 
@@ -335,7 +344,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
numattrs++;
val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
csio_append_attrib(, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
-  (uint8_t *),
+  ,
   FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
numattrs++;
 
@@ -346,23 +355,22 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
else
val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
csio_append_attrib(, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
-  (uint8_t *),
-  FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
+  , FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
numattrs++;
 
mfs = ln->ln_sparm.csp.sp_bb_data;
csio_append_attrib(, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
-  (uint8_t *), FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
+  , sizeof(mfs));
numattrs++;
 
strcpy(buf, "csiostor");
csio_append_attrib(, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
-  (uint16_t)strlen(buf));
+  strlen(buf));
numattrs++;
 
if (!csio_hostname(buf, sizeof(buf))) {
csio_append_attrib(, FC_FDMI_PORT_ATTR_HOSTNAME,
-  buf, (uint16_t)strlen(buf));
+  buf, strlen(buf));
numattrs++;
}
attrib_blk->numattrs = htonl(numattrs);
@@ -444,33 +452,32 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
 
strcpy(buf, "Chelsio Communications");
csio_append_attrib(, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
-  (uint16_t)strlen(buf));
+  strlen(buf));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_SERIALNUMBER,
-  hw->vpd.sn, (uint16_t)sizeof(hw->vpd.sn));
+  hw->vpd.sn, sizeof(hw->vpd.sn));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
-  (uint16_t)sizeof(hw->vpd.id));
+  sizeof(hw->vpd.id));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
-  hw->model_desc, (uint16_t)strlen(hw->model_desc));
+  hw->model_desc, strlen(hw->model_desc));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_HARDWAREVERSION,
-  hw->hw_ver, (uint16_t)sizeof(hw->hw_ver));
+  hw->hw_ver, sizeof(hw->hw_ver));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
-  hw->fwrev_str, (uint16_t)strlen(hw->fwrev_str));
+  

[PATCH AUTOSEL for 4.4 023/162] scsi: csiostor: Avoid content leaks and casts

2018-04-08 Thread Sasha Levin
From: Kees Cook 

[ Upstream commit 42c335f7e67029d2e01711f2f2bc6252277c8993 ]

When copying attributes, the len argument was padded out and the
resulting memcpy() would copy beyond the end of the source buffer.
Avoid this, and use size_t for val_len to avoid all the casts.
Similarly, avoid source buffer casts and use void *.

Additionally enforces val_len can be represented by u16 and that the DMA
buffer was not overflowed. Fixes the size of mfa, which is not
FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN (but it will be padded up to 4). This
was noticed by the future CONFIG_FORTIFY_SOURCE checks.

Cc: Daniel Micay 
Signed-off-by: Kees Cook 
Acked-by: Varun Prakash 
Signed-off-by: Martin K. Petersen 
Signed-off-by: Sasha Levin 
---
 drivers/scsi/csiostor/csio_lnode.c | 43 +++---
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/csiostor/csio_lnode.c 
b/drivers/scsi/csiostor/csio_lnode.c
index c00b2ff72b55..be5ee2d37815 100644
--- a/drivers/scsi/csiostor/csio_lnode.c
+++ b/drivers/scsi/csiostor/csio_lnode.c
@@ -238,14 +238,23 @@ csio_osname(uint8_t *buf, size_t buf_len)
 }
 
 static inline void
-csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len)
+csio_append_attrib(uint8_t **ptr, uint16_t type, void *val, size_t val_len)
 {
+   uint16_t len;
struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr;
+
+   if (WARN_ON(val_len > U16_MAX))
+   return;
+
+   len = val_len;
+
ae->type = htons(type);
len += 4;   /* includes attribute type and length */
len = (len + 3) & ~3;   /* should be multiple of 4 bytes */
ae->len = htons(len);
-   memcpy(ae->value, val, len);
+   memcpy(ae->value, val, val_len);
+   if (len > val_len)
+   memset(ae->value + val_len, 0, len - val_len);
*ptr += len;
 }
 
@@ -335,7 +344,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
numattrs++;
val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
csio_append_attrib(, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
-  (uint8_t *),
+  ,
   FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
numattrs++;
 
@@ -346,23 +355,22 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
else
val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
csio_append_attrib(, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
-  (uint8_t *),
-  FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
+  , FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
numattrs++;
 
mfs = ln->ln_sparm.csp.sp_bb_data;
csio_append_attrib(, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
-  (uint8_t *), FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
+  , sizeof(mfs));
numattrs++;
 
strcpy(buf, "csiostor");
csio_append_attrib(, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
-  (uint16_t)strlen(buf));
+  strlen(buf));
numattrs++;
 
if (!csio_hostname(buf, sizeof(buf))) {
csio_append_attrib(, FC_FDMI_PORT_ATTR_HOSTNAME,
-  buf, (uint16_t)strlen(buf));
+  buf, strlen(buf));
numattrs++;
}
attrib_blk->numattrs = htonl(numattrs);
@@ -444,33 +452,32 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct 
csio_ioreq *fdmi_req)
 
strcpy(buf, "Chelsio Communications");
csio_append_attrib(, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
-  (uint16_t)strlen(buf));
+  strlen(buf));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_SERIALNUMBER,
-  hw->vpd.sn, (uint16_t)sizeof(hw->vpd.sn));
+  hw->vpd.sn, sizeof(hw->vpd.sn));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
-  (uint16_t)sizeof(hw->vpd.id));
+  sizeof(hw->vpd.id));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
-  hw->model_desc, (uint16_t)strlen(hw->model_desc));
+  hw->model_desc, strlen(hw->model_desc));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_HARDWAREVERSION,
-  hw->hw_ver, (uint16_t)sizeof(hw->hw_ver));
+  hw->hw_ver, sizeof(hw->hw_ver));
numattrs++;
csio_append_attrib(, FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
-  hw->fwrev_str, (uint16_t)strlen(hw->fwrev_str));
+  hw->fwrev_str, strlen(hw->fwrev_str));
numattrs++;
 
if (!csio_osname(buf, sizeof(buf))) {
csio_append_attrib(,