changeset 5157:55436046775e

6608255 zero_spi_check() doesn't properly handle split-mblk data packets
author danmcd
date Mon, 01 Oct 2007 15:05:46 -0700
parents 6b4e412afcf5
children 2ccc7eeb32f8
files usr/src/uts/common/inet/ip/ip.c
diffstat 1 files changed, 26 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip.c	Mon Oct 01 14:01:48 2007 -0700
+++ b/usr/src/uts/common/inet/ip/ip.c	Mon Oct 01 15:05:46 2007 -0700
@@ -6942,23 +6942,26 @@
 
 /*
  * If we have a IPsec NAT-Traversal packet, strip the zero-SPI or
- * pass it along to ESP if the SPI is non-zero.
- *
- * One of three things can happen, all of which affect the passed-in mblk:
- *
- * 1.) The packet is stock UDP and has had its zero-SPI stripped.  Return TRUE.
- *     (NOTE:  ICMP messages that go through here just get returned.)
- *
- * 2.) The packet is ESP-in-UDP, has been transformed into an equivalent
- *     ESP packet, and is passed along to ESP.  Return FALSE.
- *
- * 3.) The packet is an ESP-in-UDP Keepalive.  Drop it and return FALSE.
+ * pass it along to ESP if the SPI is non-zero.  Returns TRUE if the mblk
+ * is not consumed.
+ *
+ * One of four things can happen, all of which affect the passed-in mblk:
+ *
+ * 1.) ICMP messages that go through here just get returned TRUE.
+ *
+ * 2.) The packet is stock UDP and gets its zero-SPI stripped.  Return TRUE.
+ *
+ * 3.) The packet is ESP-in-UDP, gets transformed into an equivalent
+ *     ESP packet, and is passed along to ESP for consumption.  Return FALSE.
+ *
+ * 4.) The packet is an ESP-in-UDP Keepalive.  Drop it and return FALSE.
  */
 static boolean_t
-zero_spi_check(queue_t *q, mblk_t *mp, ipha_t *ipha, ire_t *ire,
-    ill_t *recv_ill, ipsec_stack_t *ipss)
-{
-	int shift, plen, iph_len = IPH_HDR_LENGTH(ipha);
+zero_spi_check(queue_t *q, mblk_t *mp, ire_t *ire, ill_t *recv_ill,
+    ipsec_stack_t *ipss)
+{
+	int shift, plen, iph_len;
+	ipha_t *ipha;
 	udpha_t *udpha;
 	uint32_t *spi;
 	uint8_t *orptr;
@@ -6977,12 +6980,12 @@
 		/* Bunch of reality checks for DEBUG kernels... */
 		ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION);
 		ASSERT(((ipha_t *)mp->b_rptr)->ipha_protocol == IPPROTO_ICMP);
-		ASSERT((uint8_t *)ipha != mp->b_rptr);
 
 		return (B_TRUE);
 	}
 
-	ASSERT((uint8_t *)ipha == mp->b_rptr);
+	ipha = (ipha_t *)mp->b_rptr;
+	iph_len = IPH_HDR_LENGTH(ipha);
 	plen = ntohs(ipha->ipha_length);
 
 	if (plen - iph_len - sizeof (udpha_t) < sizeof (uint32_t)) {
@@ -7000,17 +7003,15 @@
 	}
 
 	if (MBLKL(mp) < iph_len + sizeof (udpha_t) + sizeof (*spi)) {
-		mblk_t *tmp = msgpullup(mp, -1);
-
 		/* might as well pull it all up - it might be ESP. */
-		if (tmp == NULL) {
+		if (!pullupmsg(mp, -1)) {
 			ip_drop_packet(mp, B_TRUE, recv_ill, NULL,
 			    DROPPER(ipss, ipds_esp_nomem),
 			    &ipss->ipsec_dropper);
 			return (B_FALSE);
 		}
-		freemsg(mp);
-		mp = tmp;
+
+		ipha = (ipha_t *)mp->b_rptr;
 	}
 	spi = (uint32_t *)(mp->b_rptr + iph_len + sizeof (udpha_t));
 	if (*spi == 0) {
@@ -7123,10 +7124,8 @@
 			return;
 		}
 
-		if (!zero_spi_check(ill->ill_rq, mp, ipha, NULL, recv_ill,
-		    ipss)) {
-			return;
-		}
+		if (!zero_spi_check(ill->ill_rq, mp, NULL, recv_ill, ipss))
+			return;
 	}
 
 	/* Handle options. */
@@ -12188,7 +12187,7 @@
 		}
 
 		/* "ill" is "recv_ill" in actuality. */
-		if (!zero_spi_check(q, *mpp, ipha, ire, ill, ipss))
+		if (!zero_spi_check(q, *mpp, ire, ill, ipss))
 			return (B_FALSE);
 
 		/* Else continue like a normal UDP packet. */