Hi,
short version: push the netlock from frag6_slowtimo into frag6_freef
around icmp6_error.
long version:
visa removed the netlock from frag6_slowtimo() entirely in frag6.c 1.79.
bluhm reintroduced it soon after, in 1.81, because of a lock assertion in
rt_match().
Although mpi removed *that* assertion from rt_match() in route.c 1.369, a
separate lock assertion remains in rtrequest(), and because the call chain
icmp6_error -> icmp6_reflect -> rt_match -> rt_clone -> rtrequest
is, I think, possible, we still need the netlock around icmp6_error. So
the best we can do here is push it into frag6_freef() where you only need
it once per mbuf chain.
--
Discussed with bluhm/kn and tested by kn. Everything in the frag6
regress tests pass.
Thoughts? ok?
--
Scott Cheloha
Index: sys/netinet6/frag6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/frag6.c,v
retrieving revision 1.82
diff -u -p -r1.82 frag6.c
--- sys/netinet6/frag6.c 1 Feb 2018 21:11:33 -0000 1.82
+++ sys/netinet6/frag6.c 16 Aug 2018 20:12:44 -0000
@@ -540,8 +540,10 @@ frag6_freef(struct ip6q *q6)
ip6->ip6_src = q6->ip6q_src;
ip6->ip6_dst = q6->ip6q_dst;
+ NET_LOCK();
icmp6_error(m, ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_REASSEMBLY, 0);
+ NET_UNLOCK();
} else
m_freem(m);
pool_put(&ip6af_pool, af6);
@@ -599,12 +601,8 @@ frag6_slowtimo(void)
mtx_leave(&frag6_mutex);
- if (!TAILQ_EMPTY(&rmq6)) {
- NET_LOCK();
- while ((q6 = TAILQ_FIRST(&rmq6)) != NULL) {
- TAILQ_REMOVE(&rmq6, q6, ip6q_queue);
- frag6_freef(q6);
- }
- NET_UNLOCK();
+ while ((q6 = TAILQ_FIRST(&rmq6)) != NULL) {
+ TAILQ_REMOVE(&rmq6, q6, ip6q_queue);
+ frag6_freef(q6);
}
}