summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2005-08-29 19:58:56 +0000
committerandre <andre@FreeBSD.org>2005-08-29 19:58:56 +0000
commit139f31aa37b3379cf4dac2aa734345c03a305123 (patch)
tree9d56a129a9c3cbb0284b960719d57c85e96c1425
parent71f036e379e29d52810f39a7ae320ea932e39f32 (diff)
downloadFreeBSD-src-139f31aa37b3379cf4dac2aa734345c03a305123.zip
FreeBSD-src-139f31aa37b3379cf4dac2aa734345c03a305123.tar.gz
Add m_sanity(struct mbuf *m, int sanitize) to do some heavy sanity
checking on mbuf's and mbuf chains. Set sanitize to 1 to garble illegal things and have them blow up later when used/accessed. m_sanity()'s main purpose is for KASSERT()'s and debugging of non- kosher mbuf manipulation (of which we have a number of). Reviewed by: glebius
-rw-r--r--sys/kern/uipc_mbuf.c95
-rw-r--r--sys/sys/mbuf.h1
2 files changed, 96 insertions, 0 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 6932245..dd51e51 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -294,6 +294,101 @@ m_demote(struct mbuf *m0, int all)
}
/*
+ * Sanity checks on mbuf (chain).
+ * Returns 0 bad, 1 good, panic worse.
+ * sanitize, 0 run M_SANITY_ACTION, 1 garble things so they blow up later.
+ */
+int
+m_sanity(struct mbuf *m0, int sanitize)
+{
+ struct mbuf *m;
+ caddr_t a, b;
+ int pktlen = 0;
+
+#define M_SANITY_ACTION(s) return (0)
+/* #define M_SANITY_ACTION(s) panic("mbuf %p: " s, m) */
+
+ m = m0;
+ while (m) {
+ /*
+ * Basic pointer checks. If any of these fails then some
+ * unrelated kernel memory before or after us is trashed.
+ * No way to recover from that.
+ */
+ a = (m->m_flags & M_EXT ? m->m_ext.ext_buf :
+ (m->m_flags & M_PKTHDR ? (caddr_t)(&m->m_pktdat) :
+ (caddr_t)(&m->m_dat)) );
+ b = (caddr_t)(a + (m->m_flags & M_EXT ? m->m_ext.ext_size :
+ (m->m_flags & M_PKTHDR ? MHLEN : MLEN)));
+ if ((caddr_t)m->m_data < a)
+ M_SANITY_ACTION("m_data outside mbuf data range left");
+ if ((caddr_t)m->m_data > b)
+ M_SANITY_ACTION("m_data outside mbuf data range right");
+ if ((caddr_t)m->m_data + m->m_len > b)
+ M_SANITY_ACTION("m_data + m_len exeeds mbuf space");
+ if (m->m_flags & M_PKTHDR && m->m_pkthdr.header) {
+ if ((caddr_t)m->m_pkthdr.header < a ||
+ (caddr_t)m->m_pkthdr.header > b)
+ M_SANITY_ACTION("m_pkthdr.header outside mbuf data range");
+ }
+
+ /* m->m_nextpkt may only be set on first mbuf in chain. */
+ if (m != m0 && m->m_nextpkt) {
+ if (sanitize) {
+ m_freem(m->m_nextpkt);
+ m->m_nextpkt = (struct mbuf *)0xDEADC0DE;
+ } else
+ M_SANITY_ACTION("m->m_nextpkt on in-chain mbuf");
+ }
+
+ /* correct type correlations. */
+ if (m->m_type == MT_HEADER && !(m->m_flags & M_PKTHDR)) {
+ if (sanitize)
+ m->m_type = MT_DATA;
+ else
+ M_SANITY_ACTION("MT_HEADER set but not M_PKTHDR");
+ }
+
+ /* packet length (not mbuf length!) calculation */
+ if (m0->m_flags & M_PKTHDR)
+ pktlen += m->m_len;
+
+ /* m_tags may only be attached to first mbuf in chain. */
+ if (m != m0 && m->m_flags & M_PKTHDR &&
+ !SLIST_EMPTY(&m->m_pkthdr.tags)) {
+ if (sanitize) {
+ m_tag_delete_chain(m, NULL);
+ /* put in 0xDEADC0DE perhaps? */
+ }
+ else
+ M_SANITY_ACTION("m_tags on in-chain mbuf");
+ }
+
+ /* M_PKTHDR may only be set on first mbuf in chain */
+ if (m != m0 && m->m_flags & M_PKTHDR) {
+ if (sanitize) {
+ bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
+ m->m_flags &= ~M_PKTHDR;
+ /* put in 0xDEADCODE and leave hdr flag in */
+ } else
+ M_SANITY_ACTION("M_PKTHDR on in-chain mbuf");
+ }
+
+ m = m->m_next;
+ }
+ if (pktlen && pktlen != m0->m_pkthdr.len) {
+ if (sanitize)
+ m0->m_pkthdr.len = 0;
+ else
+ M_SANITY_ACTION("m_pkthdr.len != mbuf chain length");
+ }
+#undef M_SANITY_ACTION
+
+ return 1;
+}
+
+
+/*
* "Move" mbuf pkthdr from "from" to "to".
* "from" must have M_PKTHDR set, and "to" must be empty.
*/
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 7f2b540..55db1b1 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -593,6 +593,7 @@ struct mbuf *m_prepend(struct mbuf *, int, int);
void m_print(const struct mbuf *, int);
struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
struct mbuf *m_pullup(struct mbuf *, int);
+int m_sanity(struct mbuf *, int);
struct mbuf *m_split(struct mbuf *, int, int);
struct mbuf *m_uiotombuf(struct uio *, int, int, int);
OpenPOWER on IntegriCloud