summaryrefslogtreecommitdiffstats
path: root/sys/netatalk/ddp_output.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-22 10:23:54 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-22 10:23:54 +0000
commit5daa0c14237b29afdd8225eba0c34cc0c8238ca3 (patch)
tree8b6fd873a14e459bd3341eef4e3b417559fcfec3 /sys/netatalk/ddp_output.c
parent1a759a35f242325e2263831a412a94a6e90ca317 (diff)
downloadFreeBSD-src-5daa0c14237b29afdd8225eba0c34cc0c8238ca3.zip
FreeBSD-src-5daa0c14237b29afdd8225eba0c34cc0c8238ca3.tar.gz
Add a global rwlock, at_ifaddr_rw, to protect the global netatalk
address lists, at_ifaddr_list. Acquire the lock, and use ifaddr refcounts where necessary, to close most known address-related races in netatalk. Annotate one potential race in at_control() where we acquire an ifaddr reference, drop the global lock, and scrub the address from the ifnet before re-acquiring the global lock, which could allow for a writer-writer race. MFC after: 3 weeks
Diffstat (limited to 'sys/netatalk/ddp_output.c')
-rw-r--r--sys/netatalk/ddp_output.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/netatalk/ddp_output.c b/sys/netatalk/ddp_output.c
index 6fa75ce..a820f24 100644
--- a/sys/netatalk/ddp_output.c
+++ b/sys/netatalk/ddp_output.c
@@ -142,12 +142,16 @@ ddp_route(struct mbuf *m, struct route *ro)
if ((ro->ro_rt != NULL) && (ro->ro_rt->rt_ifa) &&
(ifp = ro->ro_rt->rt_ifa->ifa_ifp)) {
net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net);
+ AT_IFADDR_RLOCK();
for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
if (((net == 0) || (aa->aa_ifp == ifp)) &&
net >= ntohs(aa->aa_firstnet) &&
net <= ntohs(aa->aa_lastnet))
break;
}
+ if (aa != NULL)
+ ifa_ref(&aa->aa_ifa);
+ AT_IFADDR_RUNLOCK();
} else {
m_freem(m);
#ifdef NETATALK_DEBUG
@@ -199,6 +203,7 @@ ddp_route(struct mbuf *m, struct route *ro)
if (!(aa->aa_flags & AFA_PHASE2)) {
MGET(m0, M_DONTWAIT, MT_DATA);
if (m0 == NULL) {
+ ifa_free(&aa->aa_ifa);
m_freem(m);
printf("ddp_route: no buffers\n");
return (ENOBUFS);
@@ -231,8 +236,11 @@ ddp_route(struct mbuf *m, struct route *ro)
if ((satosat(&aa->aa_addr)->sat_addr.s_net ==
satosat(&ro->ro_dst)->sat_addr.s_net) &&
(satosat(&aa->aa_addr)->sat_addr.s_node ==
- satosat(&ro->ro_dst)->sat_addr.s_node))
+ satosat(&ro->ro_dst)->sat_addr.s_node)) {
+ ifa_free(&aa->aa_ifa);
return (if_simloop(ifp, m, gate.sat_family, 0));
+ }
+ ifa_free(&aa->aa_ifa);
/* XXX */
return ((*ifp->if_output)(ifp, m, (struct sockaddr *)&gate, NULL));
OpenPOWER on IntegriCloud