diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2008-05-11 03:50:24 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2008-05-11 03:50:24 +0000 |
commit | 622648761398208349bd99d0d8e89f0f6974ba58 (patch) | |
tree | 21861743eb1b66b8609237fdb44d847a0f0ea7f6 /sys | |
parent | 164134f8f59a73f9a2f251a14785239744989316 (diff) |
Try harder to avoid corrupting the mbuf pool. Stuff any mbuf chain in
ln_hold or la_hold into temporary storage and null ln_hold or
la_hold before manually processing the mbuf chain. Discard the mbuf chain
if it is put back in the hold area.
ok claudio@ markus@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/if_ether.c | 13 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 17 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 13 |
3 files changed, 32 insertions, 11 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 77f4718a1b6..1f1adef8b8b 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.c,v 1.73 2008/05/09 15:48:59 claudio Exp $ */ +/* $OpenBSD: if_ether.c,v 1.74 2008/05/11 03:50:23 krw Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* @@ -696,9 +696,14 @@ in_arpinput(m) rt->rt_flags &= ~RTF_REJECT; la->la_asked = 0; if (la->la_hold) { - (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold, - rt_key(rt), rt); - la->la_hold = 0; + struct mbuf *n = la->la_hold; + la->la_hold = NULL; + (*ac->ac_if.if_output)(&ac->ac_if, n, rt_key(rt), rt); + if (la->la_hold == n) { + /* n is back in la_hold. Discard. */ + m_freem(la->la_hold); + la->la_hold = NULL; + } } } reply: diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index a9c7da10b2f..05229c032a1 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.75 2007/10/01 16:39:30 krw Exp $ */ +/* $OpenBSD: nd6.c,v 1.76 2008/05/11 03:50:23 krw Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -446,6 +446,11 @@ nd6_llinfo_timer(void *arg) icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); + if (ln->ln_hold == m) { + /* m is back in ln_hold. Discard. */ + m_freem(ln->ln_hold); + ln->ln_hold = NULL; + } } (void)nd6_free(rt, 0); ln = NULL; @@ -1579,13 +1584,19 @@ fail: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz); if (ln->ln_hold) { + struct mbuf *n = ln->ln_hold; + ln->ln_hold = NULL; /* * we assume ifp is not a p2p here, so just * set the 2nd argument as the 1st one. */ - nd6_output(ifp, ifp, ln->ln_hold, + nd6_output(ifp, ifp, n, (struct sockaddr_in6 *)rt_key(rt), rt); - ln->ln_hold = NULL; + if (ln->ln_hold == n) { + /* n is back in ln_hold. Discard. */ + m_freem(ln->ln_hold); + ln->ln_hold = NULL; + } } } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { /* probe right away */ diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index d2e8967df92..355af558a00 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_nbr.c,v 1.49 2008/04/18 06:42:20 djm Exp $ */ +/* $OpenBSD: nd6_nbr.c,v 1.50 2008/05/11 03:50:23 krw Exp $ */ /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */ /* @@ -803,13 +803,18 @@ nd6_na_input(m, off, icmp6len) rt->rt_flags &= ~RTF_REJECT; ln->ln_asked = 0; if (ln->ln_hold) { + struct mbuf *n = ln->ln_hold; + ln->ln_hold = NULL; /* * we assume ifp is not a loopback here, so just set the 2nd * argument as the 1st one. */ - nd6_output(ifp, ifp, ln->ln_hold, - (struct sockaddr_in6 *)rt_key(rt), rt); - ln->ln_hold = NULL; + nd6_output(ifp, ifp, n, (struct sockaddr_in6 *)rt_key(rt), rt); + if (ln->ln_hold == n) { + /* n is back in ln_hold. Discard. */ + m_freem(ln->ln_hold); + ln->ln_hold = NULL; + } } freeit: |