summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2008-05-11 03:50:24 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2008-05-11 03:50:24 +0000
commit622648761398208349bd99d0d8e89f0f6974ba58 (patch)
tree21861743eb1b66b8609237fdb44d847a0f0ea7f6 /sys
parent164134f8f59a73f9a2f251a14785239744989316 (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.c13
-rw-r--r--sys/netinet6/nd6.c17
-rw-r--r--sys/netinet6/nd6_nbr.c13
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: