aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan T. Looney <jtl@FreeBSD.org>2018-10-09 13:26:06 +0000
committerJonathan T. Looney <jtl@FreeBSD.org>2018-10-09 13:26:06 +0000
commit13c6ba6d940e5333078e5f14dd9068c499f1a89f (patch)
tree8f67a8b0ee88497d8c5bb97897d4eb323bf8bd7d /sys
parentfc5e4199a63c7286a14897dcd235185d33dc8437 (diff)
downloadsrc-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.c11
-rw-r--r--sys/netinet/ip_options.c5
-rw-r--r--sys/netinet6/udp6_usrreq.c2
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);
}
/*