svn commit: r220488 - stable/7/sys/netinet6
Bjoern A. Zeeb
bz at FreeBSD.org
Sat Apr 9 12:15:41 UTC 2011
Author: bz
Date: Sat Apr 9 12:15:40 2011
New Revision: 220488
URL: http://svn.freebsd.org/changeset/base/220488
Log:
MFC r219562:
Make sure the locally cached value of rt->rt_gateway stays stable,
even after dropping the reference and unlocking. Previously we
have dereferenced a NULL pointer (after r121765).
Simply unlocking after the block does not work either because of
lock ordering (see r121765) and in addition we would still hold
a pointer to something that might be gone by the time we access it.
Thus take a copy of the value rather than just caching the pointer.
Submitted by: chenyl (netstar2008 126.com) (initial version)
PR: kern/151908
Modified:
stable/7/sys/netinet6/nd6_nbr.c
Directory Properties:
stable/7/sys/ (props changed)
stable/7/sys/cddl/contrib/opensolaris/ (props changed)
stable/7/sys/contrib/dev/acpica/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
Modified: stable/7/sys/netinet6/nd6_nbr.c
==============================================================================
--- stable/7/sys/netinet6/nd6_nbr.c Sat Apr 9 12:11:19 2011 (r220487)
+++ stable/7/sys/netinet6/nd6_nbr.c Sat Apr 9 12:15:40 2011 (r220488)
@@ -106,7 +106,7 @@ nd6_ns_input(struct mbuf *m, int off, in
int anycast = 0, proxy = 0, tentative = 0;
int tlladdr;
union nd_opts ndopts;
- struct sockaddr_dl *proxydl = NULL;
+ struct sockaddr_dl proxydl;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
#ifndef PULLDOWN_TEST
@@ -235,18 +235,25 @@ nd6_ns_input(struct mbuf *m, int off, in
rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0);
need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
rt->rt_gateway->sa_family == AF_LINK);
- if (rt)
+ if (rt != NULL) {
+ /*
+ * Make a copy while we can be sure that rt_gateway
+ * is still stable before unlocking to avoid lock
+ * order problems. proxydl will only be used if
+ * proxy will be set in the next block.
+ */
+ if (need_proxy)
+ proxydl = *SDL(rt->rt_gateway);
RTFREE_LOCKED(rt);
+ }
if (need_proxy) {
/*
* proxy NDP for single entry
*/
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
- if (ifa) {
+ if (ifa)
proxy = 1;
- proxydl = SDL(rt->rt_gateway);
- }
}
}
if (ifa == NULL) {
@@ -320,7 +327,7 @@ nd6_ns_input(struct mbuf *m, int off, in
nd6_na_output(ifp, &in6_all, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
(ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
- tlladdr, (struct sockaddr *)proxydl);
+ tlladdr, (struct sockaddr *)&proxydl);
goto freeit;
}
@@ -330,7 +337,7 @@ nd6_ns_input(struct mbuf *m, int off, in
nd6_na_output(ifp, &saddr6, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
(ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
- tlladdr, (struct sockaddr *)proxydl);
+ tlladdr, (struct sockaddr *)&proxydl);
freeit:
m_freem(m);
return;
More information about the svn-src-all
mailing list