aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRyan Stone <rstone@FreeBSD.org>2016-08-18 22:59:10 +0000
committerRyan Stone <rstone@FreeBSD.org>2016-08-18 22:59:10 +0000
commit11f2a7cd67709487d0bec5209ac4f451fe8b0c19 (patch)
treed63595cc3c31db8f535ec51f0d550a35b481e2ed /sys
parent41029db13f2e6a7e03e55a0b0aacd6c7acf37621 (diff)
Fix unlocked access to ifnet address list
in_broadcast() was iterating over the ifnet address list without first taking an IF_ADDR_RLOCK. This could cause a panic if a concurrent operation modified the list. Reviewed by: bz MFC after: 2 months Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D7227
Notes
svn path=/head/; revision=304437
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/in.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 067138ade407..cf1c81489d14 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -954,21 +954,27 @@ int
in_broadcast(struct in_addr in, struct ifnet *ifp)
{
register struct ifaddr *ifa;
+ int found;
if (in.s_addr == INADDR_BROADCAST ||
in.s_addr == INADDR_ANY)
return (1);
if ((ifp->if_flags & IFF_BROADCAST) == 0)
return (0);
+ found = 0;
/*
* Look through the list of addresses for a match
* with a broadcast address.
*/
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET &&
- in_ifaddr_broadcast(in, (struct in_ifaddr *)ifa))
- return (1);
- return (0);
+ in_ifaddr_broadcast(in, (struct in_ifaddr *)ifa)) {
+ found = 1;
+ break;
+ }
+ IF_ADDR_RUNLOCK(ifp);
+ return (found);
}
/*