Hello Hiral Patel,

The patch d3c995f1dcf9: "[SCSI] fnic: FIP VLAN Discovery Feature
Support" from Feb 25, 2013, leads to the following
static checker warning:

        drivers/scsi/fnic/fnic_fcs.c:278 is_fnic_fip_flogi_reject()
        warn: is it ok to set 'els_len' to negative?

This is some unpushable debug code on my Smatch system.  It is sort of
a nonsense warning because Smatch has run into an "impossible" condition
because of a bug in Smatch but also because of bug in
fnic_fcoe_send_vlan_req().

drivers/scsi/fnic/fnic_fcs.c
   251          fiph = (struct fip_header *)skb->data;
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fiph is untrusted data.  We don't trust the network.  This is a rule of
Linux.

   252          op = ntohs(fiph->fip_op);
   253          sub = fiph->fip_subcode;
   254  
   255          if (op != FIP_OP_LS)
   256                  return 0;
   257  
   258          if (sub != FIP_SC_REP)
   259                  return 0;
   260  
   261          rlen = ntohs(fiph->fip_dl_len) * 4;
   262          if (rlen + sizeof(*fiph) > skb->len)
   263                  return 0;
   264  
   265          desc = (struct fip_desc *)(fiph + 1);
   266          dlen = desc->fip_dlen * FIP_BPW;
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
desc->fip_dlen is u8 type so it could be a number between 0-255.  That's
fine.
FIP_BPW is 4.
Here is the bug in Smatch.  It looks at the sender code and says that
desc->fip_dlen is set to either 2 or 4.  So now dlen is in 8-16 range.

   267  
   268          if (desc->fip_dtype == FIP_DT_FLOGI) {
   269  
   270                  shost_printk(KERN_DEBUG, lport->host,
   271                            " FIP TYPE FLOGI: fab name:%llx "
   272                            "vfid:%d map:%x\n",
   273                            fip->sel_fcf->fabric_name, fip->sel_fcf->vfid,
   274                            fip->sel_fcf->fc_map);
   275                  if (dlen < sizeof(*els) + sizeof(*fh) + 1)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8-16 is always less than 29 so this condition is always true.

   276                          return 0;
   277  
   278                  els_len = dlen - sizeof(*els);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We are in an impossible condition and Smatch doesn't know the possible
values of "dlen" any more so it generates the warning.

   279                  els = (struct fip_encaps *)desc;
   280                  fh = (struct fc_frame_header *)(els + 1);
   281                  els_dtype = desc->fip_dtype;
   282  
   283                  if (!fh)
   284                          return 0;
   285  
   286                  /*
   287                   * ELS command code, reason and explanation should be = 
Reject,
   288                   * unsupported command and insufficient resource
   289                   */
   290                  els_op = *(u8 *)(fh + 1);
   291                  if (els_op == ELS_LS_RJT) {
   292                          shost_printk(KERN_INFO, lport->host,
   293                                    "Flogi Request Rejected by Switch\n");
   294                          return 1;
   295                  }
   296                  shost_printk(KERN_INFO, lport->host,
   297                                  "Flogi Request Accepted by Switch\n");
   298          }
   299          return 0;
   300  }
   301  
   302  static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
   303  {
   304          struct fcoe_ctlr *fip = &fnic->ctlr;
   305          struct fnic_stats *fnic_stats = &fnic->fnic_stats;
   306          struct sk_buff *skb;
   307          char *eth_fr;
   308          int fr_len;
   309          struct fip_vlan *vlan;
   310          u64 vlan_tov;
   311  
   312          fnic_fcoe_reset_vlans(fnic);
   313          fnic->set_vlan(fnic, 0);
   314          FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
   315                    "Sending VLAN request...\n");
   316          skb = dev_alloc_skb(sizeof(struct fip_vlan));
   317          if (!skb)
   318                  return;
   319  
   320          fr_len = sizeof(*vlan);
   321          eth_fr = (char *)skb->data;
   322          vlan = (struct fip_vlan *)eth_fr;
   323  
   324          memset(vlan, 0, sizeof(*vlan));
   325          memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
   326          memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN);
   327          vlan->eth.h_proto = htons(ETH_P_FIP);
   328  
   329          vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
   330          vlan->fip.fip_op = htons(FIP_OP_VLAN);
   331          vlan->fip.fip_subcode = FIP_SC_VL_REQ;
   332          vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
   333  
   334          vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
   335          vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / 
FIP_BPW;

8 / 4 = 2.  We are setting ->fib_dlen to 2.

   336          memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
   337  
   338          vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
   339          vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / 
FIP_BPW;
                                                   
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is actually a second Smatch bug which it inherited from Sparse.  It
doesn't understand packed structs correctly and think we are setting
->fib_dlen to 4 but we are setting it to 3.

   340          put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn);
   341          atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
   342  

I suspect that the size calculation is not taking
sizeof(struct fc_frame_header) into consideration properly in
fnic_fcoe_send_vlan_req()?

regards,
dan carpenter

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to