Module Name:    src
Committed By:   maxv
Date:           Sun Apr 15 07:35:49 UTC 2018

Modified Files:
        src/sys/kern: uipc_mbuf.c
        src/sys/netinet: ip_input.c
        src/sys/netinet6: ip6_input.c
        src/sys/netipsec: ipsec_input.c
        src/sys/sys: mbuf.h

Log Message:
Introduce a m_verify_packet function, that verifies the mbuf chain of a
packet to ensure it is not malformed. Call this function in "points of
interest", that are the IPv4/IPv6/IPsec entry points. There could be more.

We use M_VERIFY_PACKET(m), declared under DIAGNOSTIC only.

This function should not be called everywhere, especially not in places
that temporarily manipulate (and clobber) the mbuf structure; once they're
done they put the mbuf back in a correct format.


To generate a diff of this commit:
cvs rdiff -u -r1.187 -r1.188 src/sys/kern/uipc_mbuf.c
cvs rdiff -u -r1.379 -r1.380 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.196 -r1.197 src/sys/netinet6/ip6_input.c
cvs rdiff -u -r1.62 -r1.63 src/sys/netipsec/ipsec_input.c
cvs rdiff -u -r1.185 -r1.186 src/sys/sys/mbuf.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/uipc_mbuf.c
diff -u src/sys/kern/uipc_mbuf.c:1.187 src/sys/kern/uipc_mbuf.c:1.188
--- src/sys/kern/uipc_mbuf.c:1.187	Tue Apr 10 16:12:30 2018
+++ src/sys/kern/uipc_mbuf.c	Sun Apr 15 07:35:49 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_mbuf.c,v 1.187 2018/04/10 16:12:30 maxv Exp $	*/
+/*	$NetBSD: uipc_mbuf.c,v 1.188 2018/04/15 07:35:49 maxv Exp $	*/
 
 /*
  * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.187 2018/04/10 16:12:30 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.188 2018/04/15 07:35:49 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_mbuftrace.h"
@@ -1888,6 +1888,67 @@ m_claim(struct mbuf *m, struct mowner *m
 }
 #endif /* defined(MBUFTRACE) */
 
+#ifdef DIAGNOSTIC
+/*
+ * Verify that the mbuf chain is not malformed. Used only for diagnostic.
+ * Panics on error.
+ */
+void
+m_verify_packet(struct mbuf *m)
+{
+	struct mbuf *n = m;
+	char *low, *high, *dat;
+	int totlen = 0, len;
+
+	if (__predict_false((m->m_flags & M_PKTHDR) == 0)) {
+		panic("%s: mbuf doesn't have M_PKTHDR", __func__);
+	}
+
+	while (n != NULL) {
+		if (__predict_false(n->m_type == MT_FREE)) {
+			panic("%s: mbuf already freed (n = %p)", __func__, n);
+		}
+		if (__predict_false((n != m) && (n->m_flags & M_PKTHDR) != 0)) {
+			panic("%s: M_PKTHDR set on secondary mbuf", __func__);
+		}
+		if (__predict_false(n->m_nextpkt != NULL)) {
+			panic("%s: m_nextpkt not null (m_nextpkt = %p)",
+			    __func__, n->m_nextpkt);
+		}
+
+		dat = n->m_data;
+		len = n->m_len;
+
+		if (n->m_flags & M_EXT) {
+			low = n->m_ext.ext_buf;
+			high = low + n->m_ext.ext_size;
+		} else if (n->m_flags & M_PKTHDR) {
+			low = n->m_pktdat;
+			high = low + MHLEN;
+		} else {
+			low = n->m_dat;
+			high = low + MLEN;
+		}
+		if (__predict_false(dat + len <= dat)) {
+			panic("%s: incorrect length (len = %d)", __func__, len);
+		}
+		if (__predict_false((dat < low) || (dat + len > high))) {
+			panic("%s: m_data not in packet"
+			    "(dat = %p, len = %d, low = %p, high = %p)",
+			    __func__, dat, len, low, high);
+		}
+
+		totlen += len;
+		n = n->m_next;
+	}
+
+	if (__predict_false(totlen != m->m_pkthdr.len)) {
+		panic("%s: inconsistent mbuf length (%d != %d)", __func__,
+		    totlen, m->m_pkthdr.len);
+	}
+}
+#endif
+
 /*
  * Release a reference to the mbuf external storage.
  *

Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.379 src/sys/netinet/ip_input.c:1.380
--- src/sys/netinet/ip_input.c:1.379	Wed Apr 11 08:11:20 2018
+++ src/sys/netinet/ip_input.c	Sun Apr 15 07:35:49 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_input.c,v 1.379 2018/04/11 08:11:20 maxv Exp $	*/
+/*	$NetBSD: ip_input.c,v 1.380 2018/04/15 07:35:49 maxv Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.379 2018/04/11 08:11:20 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.380 2018/04/15 07:35:49 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -766,6 +766,8 @@ ours:
 		hlen = ip->ip_hl << 2;
 	}
 
+	M_VERIFY_PACKET(m);
+
 #ifdef IPSEC
 	/*
 	 * Enforce IPsec policy checking if we are seeing last header.

Index: src/sys/netinet6/ip6_input.c
diff -u src/sys/netinet6/ip6_input.c:1.196 src/sys/netinet6/ip6_input.c:1.197
--- src/sys/netinet6/ip6_input.c:1.196	Wed Apr 11 07:55:19 2018
+++ src/sys/netinet6/ip6_input.c	Sun Apr 15 07:35:49 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_input.c,v 1.196 2018/04/11 07:55:19 maxv Exp $	*/
+/*	$NetBSD: ip6_input.c,v 1.197 2018/04/15 07:35:49 maxv Exp $	*/
 /*	$KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.196 2018/04/11 07:55:19 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.197 2018/04/15 07:35:49 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_gateway.h"
@@ -748,6 +748,8 @@ hbhcheck:
 			goto bad;
 		}
 
+		M_VERIFY_PACKET(m);
+
 		/*
 		 * protection against faulty packet - there should be
 		 * more sanity checks in header chain processing.

Index: src/sys/netipsec/ipsec_input.c
diff -u src/sys/netipsec/ipsec_input.c:1.62 src/sys/netipsec/ipsec_input.c:1.63
--- src/sys/netipsec/ipsec_input.c:1.62	Mon Feb 26 09:04:29 2018
+++ src/sys/netipsec/ipsec_input.c	Sun Apr 15 07:35:49 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ipsec_input.c,v 1.62 2018/02/26 09:04:29 maxv Exp $	*/
+/*	$NetBSD: ipsec_input.c,v 1.63 2018/04/15 07:35:49 maxv Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $	*/
 /*	$OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $	*/
 
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.62 2018/02/26 09:04:29 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.63 2018/04/15 07:35:49 maxv Exp $");
 
 /*
  * IPsec input processing.
@@ -456,6 +456,8 @@ cantpull:
 #endif /* INET6 */
 #endif /* notyet */
 
+	M_VERIFY_PACKET(m);
+
 	key_sa_recordxfer(sav, m);		/* record data transfer */
 
 	if ((inetsw[ip_protox[prot]].pr_flags & PR_LASTHDR) != 0 &&
@@ -667,6 +669,8 @@ ipsec6_common_input_cb(struct mbuf *m, s
 			goto bad;
 		}
 
+		M_VERIFY_PACKET(m);
+
 		/*
 		 * Protection against faulty packet - there should be
 		 * more sanity checks in header chain processing.

Index: src/sys/sys/mbuf.h
diff -u src/sys/sys/mbuf.h:1.185 src/sys/sys/mbuf.h:1.186
--- src/sys/sys/mbuf.h:1.185	Fri Apr 13 08:44:41 2018
+++ src/sys/sys/mbuf.h	Sun Apr 15 07:35:49 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mbuf.h,v 1.185 2018/04/13 08:44:41 maxv Exp $	*/
+/*	$NetBSD: mbuf.h,v 1.186 2018/04/15 07:35:49 maxv Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
@@ -704,6 +704,12 @@ do {									\
 	(m)->m_type = t;						\
 } while (/* CONSTCOND */ 0)
 
+#ifdef DIAGNOSTIC
+#define M_VERIFY_PACKET(m)	m_verify_packet(m)
+#else
+#define M_VERIFY_PACKET(m)	/* nothing */
+#endif
+
 /* length to m_copy to copy all */
 #define	M_COPYALL	-1
 
@@ -864,6 +870,7 @@ struct	mbuf *m_copyback_cow(struct mbuf 
 int	m_makewritable(struct mbuf **, int, int, int);
 struct	mbuf *m_getcl(int, int, int);
 void	m_copydata(struct mbuf *, int, int, void *);
+void	m_verify_packet(struct mbuf *);
 struct	mbuf *m_free(struct mbuf *);
 void	m_freem(struct mbuf *);
 void	m_reclaim(void *, int);

Reply via email to