scsi: csiostor: Avoid content leaks and casts
authorKees Cook <keescook@chromium.org>
Tue, 9 May 2017 22:34:44 +0000 (15:34 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 13 Jun 2017 00:48:05 +0000 (20:48 -0400)
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 <danielmicay@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Varun Prakash <varun@chelsio.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/csiostor/csio_lnode.c

index c00b2ff72b551e48489051bf74015ba2e95c9d85..be5ee2d37815510226627261955f75d842711fd6 100644 (file)
@@ -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(&pld, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
-                          (uint8_t *)&val,
+                          &val,
                           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(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
-                          (uint8_t *)&val,
-                          FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
+                          &val, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
        numattrs++;
 
        mfs = ln->ln_sparm.csp.sp_bb_data;
        csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
-                          (uint8_t *)&mfs, FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
+                          &mfs, sizeof(mfs));
        numattrs++;
 
        strcpy(buf, "csiostor");
        csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
-                          (uint16_t)strlen(buf));
+                          strlen(buf));
        numattrs++;
 
        if (!csio_hostname(buf, sizeof(buf))) {
                csio_append_attrib(&pld, 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(&pld, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
-                          (uint16_t)strlen(buf));
+                          strlen(buf));
        numattrs++;
        csio_append_attrib(&pld, 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(&pld, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
-                          (uint16_t)sizeof(hw->vpd.id));
+                          sizeof(hw->vpd.id));
        numattrs++;
        csio_append_attrib(&pld, 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(&pld, 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(&pld, 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(&pld, FC_FDMI_HBA_ATTR_OSNAMEVERSION,
-                                  buf, (uint16_t)strlen(buf));
+                                  buf, strlen(buf));
                numattrs++;
        }
 
        csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
-                          (uint8_t *)&maxpayload,
-                          FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
+                          &maxpayload, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
        len = (uint32_t)(pld - (uint8_t *)cmd);
        numattrs++;
        attrib_blk->numattrs = htonl(numattrs);
@@ -1794,6 +1801,8 @@ csio_ln_mgmt_submit_req(struct csio_ioreq *io_req,
        struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
        int rv;
 
+       BUG_ON(pld_len > pld->len);
+
        io_req->io_cbfn = io_cbfn;      /* Upper layer callback handler */
        io_req->fw_handle = (uintptr_t) (io_req);
        io_req->eq_idx = mgmtm->eq_idx;