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
This commit is contained in:
Andre Oppermann 2005-08-29 19:58:56 +00:00
parent ed111688e9
commit a048affba5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=149599
2 changed files with 96 additions and 0 deletions

View file

@ -293,6 +293,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.

View file

@ -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);