pf: Must be in NET_EPOCH to call icmp_error

icmp_reflect(), called through icmp_error() requires us to be in NET_EPOCH.
Failure to hold it leads to the following panic (with INVARIANTS):

  panic: Assertion in_epoch(net_epoch_preempt) failed at /usr/src/sys/netinet/ip_icmp.c:742
  cpuid = 2
  time = 1571233273
  KDB: stack backtrace:
  db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00e0977920
  vpanic() at vpanic+0x17e/frame 0xfffffe00e0977980
  panic() at panic+0x43/frame 0xfffffe00e09779e0
  icmp_reflect() at icmp_reflect+0x625/frame 0xfffffe00e0977aa0
  icmp_error() at icmp_error+0x720/frame 0xfffffe00e0977b10
  pf_intr() at pf_intr+0xd5/frame 0xfffffe00e0977b50
  ithread_loop() at ithread_loop+0x1c6/frame 0xfffffe00e0977bb0
  fork_exit() at fork_exit+0x80/frame 0xfffffe00e0977bf0
  fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00e0977bf0

Note that we now enter NET_EPOCH twice if we enter ip_output() from pf_intr(),
but ip_output() will soon be converted to a function that requires epoch, so
entering NET_EPOCH directly from pf_intr() makes more sense.

Discussed with:	glebius@
This commit is contained in:
Kristof Provost 2019-10-18 03:36:26 +00:00
parent 7bf55415d5
commit a0d571cbef

View File

@ -1428,6 +1428,7 @@ pf_send(struct pf_send_entry *pfse)
void
pf_intr(void *v)
{
struct epoch_tracker et;
struct pf_send_head queue;
struct pf_send_entry *pfse, *next;
@ -1438,6 +1439,8 @@ pf_intr(void *v)
STAILQ_INIT(&V_pf_sendqueue);
PF_SENDQ_UNLOCK();
NET_EPOCH_ENTER(et);
STAILQ_FOREACH_SAFE(pfse, &queue, pfse_next, next) {
switch (pfse->pfse_type) {
#ifdef INET
@ -1464,6 +1467,7 @@ pf_intr(void *v)
}
free(pfse, M_PFTEMP);
}
NET_EPOCH_EXIT(et);
CURVNET_RESTORE();
}