--- sys/netpfil/ipfw/pmod/tcpmod.c.orig
+++ sys/netpfil/ipfw/pmod/tcpmod.c
@@ -58,7 +58,8 @@
 #define	V_tcpmod_setmss_eid	VNET(tcpmod_setmss_eid)
 
 static int
-tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss)
+tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss,
+    int *done)
 {
 	struct mbuf *m;
 	u_char *cp;
@@ -73,8 +74,10 @@
 		 * TCP header with options.
 		 */
 		*mp = m = m_pullup(m, m->m_pkthdr.len);
-		if (m == NULL)
+		if (m == NULL) {
+			*done = 1;
 			return (ret);
+		}
 	}
 	/* Parse TCP options. */
 	for (tlen -= sizeof(struct tcphdr), cp = (u_char *)(tcp + 1);
@@ -115,7 +118,7 @@
 
 #ifdef INET6
 static int
-tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss)
+tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss, int *done)
 {
 	struct ip6_hdr *ip6;
 	struct ip6_hbh *hbh;
@@ -143,13 +146,13 @@
 	/* We must have TCP options and enough data in a packet. */
 	if (hlen <= sizeof(struct tcphdr) || hlen > plen)
 		return (IP_FW_DENY);
-	return (tcpmod_setmss(mp, tcp, hlen, mss));
+	return (tcpmod_setmss(mp, tcp, hlen, mss, done));
 }
 #endif /* INET6 */
 
 #ifdef INET
 static int
-tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss)
+tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss, int *done)
 {
 	struct tcphdr *tcp;
 	struct ip *ip;
@@ -163,7 +166,7 @@
 	/* We must have TCP options and enough data in a packet. */
 	if (hlen <= sizeof(struct tcphdr) || hlen > plen)
 		return (IP_FW_DENY);
-	return (tcpmod_setmss(mp, tcp, hlen, mss));
+	return (tcpmod_setmss(mp, tcp, hlen, mss, done));
 }
 #endif /* INET */
 
@@ -207,19 +210,23 @@
 	switch (args->f_id.addr_type) {
 #ifdef INET
 		case 4:
-			ret = tcpmod_ipv4_setmss(&args->m, htons(icmd->arg1));
+			ret = tcpmod_ipv4_setmss(&args->m, htons(icmd->arg1),
+			    done);
 			break;
 #endif
 #ifdef INET6
 		case 6:
-			ret = tcpmod_ipv6_setmss(&args->m, htons(icmd->arg1));
+			ret = tcpmod_ipv6_setmss(&args->m, htons(icmd->arg1),
+			    done);
 			break;
 #endif
 	}
 	/*
 	 * We return zero in both @ret and @done on success, and ipfw_chk()
 	 * will update rule counters. Otherwise a packet will not be matched
-	 * by rule.
+	 * by rule. We passed @done around above in case we hit a fatal error
+	 * somewhere, we'll return non-zero but signal that rule processing
+	 * cannot succeed.
 	 */
 	return (ret);
 }
