diff options
| author | Ryan Stone <rstone@FreeBSD.org> | 2016-08-18 22:59:10 +0000 |
|---|---|---|
| committer | Ryan Stone <rstone@FreeBSD.org> | 2016-08-18 22:59:10 +0000 |
| commit | 11f2a7cd67709487d0bec5209ac4f451fe8b0c19 (patch) | |
| tree | d63595cc3c31db8f535ec51f0d550a35b481e2ed /sys | |
| parent | 41029db13f2e6a7e03e55a0b0aacd6c7acf37621 (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.c | 12 |
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); } /* |
