diff options
author | eri <eri@FreeBSD.org> | 2015-06-17 12:23:04 +0000 |
---|---|---|
committer | eri <eri@FreeBSD.org> | 2015-06-17 12:23:04 +0000 |
commit | 00bae218742ed1c2e299a634a5be29f881f1243d (patch) | |
tree | ef2badda46aafff4d0d97ec5ac496295a3c0077f /sys/netinet/if_ether.c | |
parent | 1574191a793bc236ab98611af46ae42fb9a6241a (diff) | |
download | FreeBSD-src-00bae218742ed1c2e299a634a5be29f881f1243d.zip FreeBSD-src-00bae218742ed1c2e299a634a5be29f881f1243d.tar.gz |
If there is a system with a bpf consumer running and a packet is wanted
to be transmitted but the arp cache entry expired, which triggers an arp request
to be sent, the bpf code might want to sleep but crash the system due
to a non sleep lock held from the arp entry not released properly.
Release the lock before calling the arp request code to solve the issue
as is done on all the other code paths.
PR: 200323
Approved by: ae, gnn(mentor)
MFC after: 1 week
Sponsored by: Netgate
Differential Revision: https://reviews.freebsd.org/D2828
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r-- | sys/netinet/if_ether.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index fec6aa0..aa370d6 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -364,6 +364,7 @@ retry: if ((la->la_flags & LLE_VALID) && ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { bcopy(&la->ll_addr, desten, ifp->if_addrlen); + renew = 0; /* * If entry has an expiry time and it is approaching, * see if we need to send an ARP request within this @@ -371,14 +372,22 @@ retry: */ if (!(la->la_flags & LLE_STATIC) && time_uptime + la->la_preempt > la->la_expire) { - arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); + renew = 1; la->la_preempt--; } if (pflags != NULL) *pflags = la->la_flags; - error = 0; - goto done; + + if (flags & LLE_EXCLUSIVE) + LLE_WUNLOCK(la); + else + LLE_RUNLOCK(la); + + if (renew == 1) + arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); + + return (0); } if (la->la_flags & LLE_STATIC) { /* should not happen! */ |