Print this page
NEX-3672 IDM module panics target when PDU has AHS length between 17 and 49
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
        
*** 22,31 ****
--- 22,32 ----
   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  /*
   * Copyright (c) 2013 by Delphix. All rights reserved.
+  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
   */
  
  #include <sys/conf.h>
  #include <sys/stat.h>
*** 857,876 ****
          }
  
          /*
           * Check actual AHS length against the amount available in the buffer
           */
          pdu->isp_hdrlen = sizeof (iscsi_hdr_t) +
              (bhs->hlength * sizeof (uint32_t));
          pdu->isp_datalen = n2h24(bhs->dlength);
  
          if (!idm_dataseglenokay(ic, pdu)) {
                  IDM_CONN_LOG(CE_WARN,
                      "idm_sorecvhdr: invalid data segment length");
                  return (IDM_STATUS_FAIL);
          }
!         if (bhs->hlength > IDM_SORX_CACHE_AHSLEN) {
                  /* Allocate a new header segment and change the callback */
                  new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP);
                  bcopy(pdu->isp_hdr, new_hdr, sizeof (iscsi_hdr_t));
                  pdu->isp_hdr = new_hdr;
                  pdu->isp_flags |= IDM_PDU_ADDL_HDR;
--- 858,882 ----
          }
  
          /*
           * Check actual AHS length against the amount available in the buffer
           */
+         if ((IDM_PDU_OPCODE(pdu) != ISCSI_OP_SCSI_CMD) &&
+             (bhs->hlength != 0)) {
+                 /* ---- hlength is only only valid for SCSI Request ---- */
+                 return (IDM_STATUS_FAIL);
+         }
          pdu->isp_hdrlen = sizeof (iscsi_hdr_t) +
              (bhs->hlength * sizeof (uint32_t));
          pdu->isp_datalen = n2h24(bhs->dlength);
  
          if (!idm_dataseglenokay(ic, pdu)) {
                  IDM_CONN_LOG(CE_WARN,
                      "idm_sorecvhdr: invalid data segment length");
                  return (IDM_STATUS_FAIL);
          }
!         if (bhs->hlength > IDM_SORX_WIRE_AHSLEN) {
                  /* Allocate a new header segment and change the callback */
                  new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP);
                  bcopy(pdu->isp_hdr, new_hdr, sizeof (iscsi_hdr_t));
                  pdu->isp_hdr = new_hdr;
                  pdu->isp_flags |= IDM_PDU_ADDL_HDR;