DragonFlyBSD Kernel Audit
DF-1827 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/iscsi/initiator/isc_soc.c b/sys/dev/disk/iscsi/initiator/isc_soc.c
--- a/sys/dev/disk/iscsi/initiator/isc_soc.c
+++ b/sys/dev/disk/iscsi/initiator/isc_soc.c
@@ -108,10 +108,27 @@
      /*
       | mbuf for the iSCSI header
       */
-     MGETHDR(mh, M_WAITOK, MT_DATA);
+     /*
+      | Compute the total iSCSI header length up-front so MH_ALIGN
+      | can seat it correctly at the END of m_pktdat.  The original
+      | code MH_ALIGN'd only the BHS (sizeof(union ipdu_u)), leaving
+      | zero trailing bytes for AHS or the header digest, so the
+      | subsequent bcopy()s wrote past m_pktdat (DF-1827).
+      */
+     {
+	  size_t hdrlen = sizeof(union ipdu_u)
+			+ (sp->hdrDigest ? sizeof(int) : 0)
+			+ pp->ahs_len;
+
+	  if (hdrlen > MHLEN) {
+	       debug(2, "iSCSI header too large (%zu > %ld)", hdrlen, (long)MHLEN);
+	       return E2BIG;
+	  }
+	  MGETHDR(mh, M_WAITOK, MT_DATA);
+	  mh->m_pkthdr.rcvif = NULL;
+	  MH_ALIGN(mh, hdrlen);
+     }
      mh->m_len = mh->m_pkthdr.len = sizeof(union ipdu_u);
-     mh->m_pkthdr.rcvif = NULL;
-     MH_ALIGN(mh, sizeof(union ipdu_u));
      bcopy(&pp->ipdu, mh->m_data, sizeof(union ipdu_u));
      mh->m_next = NULL;