diff options
author | Jonathan T. Looney <jtl@FreeBSD.org> | 2018-10-09 13:26:06 +0000 |
---|---|---|
committer | Jonathan T. Looney <jtl@FreeBSD.org> | 2018-10-09 13:26:06 +0000 |
commit | 13c6ba6d940e5333078e5f14dd9068c499f1a89f (patch) | |
tree | 8f67a8b0ee88497d8c5bb97897d4eb323bf8bd7d /sys | |
parent | fc5e4199a63c7286a14897dcd235185d33dc8437 (diff) | |
download | src-13c6ba6d940e5333078e5f14dd9068c499f1a89f.tar.gz src-13c6ba6d940e5333078e5f14dd9068c499f1a89f.zip |
There are three places where we return from a function which entered an
epoch section without exiting that epoch section. This is bad for two
reasons: the epoch section won't exit, and we will leave the epoch tracker
from the stack on the epoch list.
Fix the epoch leak by making sure we exit epoch sections before returning.
Reviewed by: ae, gallatin, mmacy
Approved by: re (gjb, kib)
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D17450
Notes
Notes:
svn path=/head/; revision=339251
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_lagg.c | 11 | ||||
-rw-r--r-- | sys/netinet/ip_options.c | 5 | ||||
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 2 |
3 files changed, 11 insertions, 7 deletions
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 50e790f25e79..b70916be8148 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -2033,15 +2033,18 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) { struct lagg_lb *lb = (struct lagg_lb *)sc->sc_psc; struct lagg_port *lp_next; - int i = 0; + int i = 0, rv; + rv = 0; bzero(&lb->lb_ports, sizeof(lb->lb_ports)); LAGG_RLOCK(); CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (lp_next == lp) continue; - if (i >= LAGG_MAX_PORTS) - return (EINVAL); + if (i >= LAGG_MAX_PORTS) { + rv = EINVAL; + break; + } if (sc->sc_ifflags & IFF_DEBUG) printf("%s: port %s at index %d\n", sc->sc_ifname, lp_next->lp_ifp->if_xname, i); @@ -2049,7 +2052,7 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) } LAGG_RUNLOCK(); - return (0); + return (rv); } static int diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index c194b258f476..393cfe0b1178 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -110,16 +110,16 @@ ip_dooptions(struct mbuf *m, int pass) struct nhop4_extended nh_ext; struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; - NET_EPOCH_ENTER(); /* Ignore or reject packets with IP options. */ if (V_ip_doopts == 0) return 0; else if (V_ip_doopts == 2) { type = ICMP_UNREACH; code = ICMP_UNREACH_FILTER_PROHIB; - goto bad; + goto bad_unlocked; } + NET_EPOCH_ENTER(); dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); @@ -388,6 +388,7 @@ dropit: return (0); bad: NET_EPOCH_EXIT(); +bad_unlocked: icmp_error(m, type, code, 0, 0); IPSTAT_INC(ips_badoptions); return (1); diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 93aebbd3440b..078954a03ef2 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -434,8 +434,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto) INP_RUNLOCK(last); } else INP_RUNLOCK(last); - INP_INFO_RUNLOCK_ET(pcbinfo, et); inp_lost: + INP_INFO_RUNLOCK_ET(pcbinfo, et); return (IPPROTO_DONE); } /* |