Hello,
On Sat, Nov 25, 2023 at 10:49:44AM +0100, [email protected] wrote:
> >Synopsis: ddb{1}> on serial console
> >Category: kernel
> >Environment:
> System : OpenBSD 7.4
> Details : OpenBSD 7.4 (GENERIC.MP) #0: Sun Oct 22 12:13:42 MDT 2023
>
> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
>
> Architecture: OpenBSD.amd64
> Machine : amd64
> >Description:
> over night the machine got to ddb{1}>
>
> ddb{1}> show panic
> *cpu1: kernel diagnostic assertion "st->timeout == PFTM_UNLINKED" failed:
> file "
> /usr/src/sys/net/pf.c", line 1844
> ddb{1}> trace
> db_enter() at db_enter+0x14
> panic(ffffffff820a5be3) at panic+0xc3
> __assert(ffffffff82121e5d,ffffffff8207ffa2,734,ffffffff8207ffd3) at
> __assert+0x 29
> pf_free_state(fffffd80d1480838) at pf_free_state+0x1ef
> pf_purge_expired_states(40,40) at pf_purge_expired_states+0x288
> pf_purge_states(0) at pf_purge_states+0x20
> taskq_thread(ffffffff824ba7d0) at taskq_thread+0x100
> end trace frame: 0x0, count: -7
>
> ddb{1}> boot dump
> syncing disks...
>
> I tried to get core dump, but the machines freezed. I had to ask technical
> support to physicaly power off / power up the machine.
>
The same issue got reported already by other users [1]. few users seem
to happily run diff which fixes the issue [2]. The same diff is attached.
thanks and
regards
sashan
[1] https://marc.info/?t=169896604700001&r=1&w=2
[2] https://marc.info/?l=openbsd-bugs&m=169903486617859&w=2
--------8<---------------8<---------------8<------------------8<--------
Index: net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.1186
diff -u -p -r1.1186 pf.c
--- net/pf.c 8 Sep 2023 13:40:52 -0000 1.1186
+++ net/pf.c 26 Nov 2023 09:59:12 -0000
@@ -469,6 +469,15 @@ pf_state_list_remove(struct pf_state_lis
pf_state_unref(st); /* list no longer references the state */
}
+void
+pf_update_state_timeout(struct pf_state *st, int to)
+{
+ mtx_enter(&st->mtx);
+ if (st->timeout != PFTM_UNLINKED)
+ st->timeout = to;
+ mtx_leave(&st->mtx);
+}
+
int
pf_src_connlimit(struct pf_state **stp)
{
@@ -549,7 +558,7 @@ pf_src_connlimit(struct pf_state **stp)
((*stp)->rule.ptr->flush &
PF_FLUSH_GLOBAL ||
(*stp)->rule.ptr == st->rule.ptr)) {
- st->timeout = PFTM_PURGE;
+ pf_update_state_timeout(st, PFTM_PURGE);
pf_set_protostate(st, PF_PEER_BOTH,
TCPS_CLOSED);
killed++;
@@ -563,7 +572,7 @@ pf_src_connlimit(struct pf_state **stp)
}
/* kill this state */
- (*stp)->timeout = PFTM_PURGE;
+ pf_update_state_timeout(*stp, PFTM_PURGE);
pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_CLOSED);
return (1);
}
@@ -1761,7 +1770,9 @@ pf_remove_state(struct pf_state *st)
if (st->timeout == PFTM_UNLINKED)
return;
+ mtx_enter(&st->mtx);
st->timeout = PFTM_UNLINKED;
+ mtx_leave(&st->mtx);
/* handle load balancing related tasks */
pf_postprocess_addr(st);
@@ -1816,7 +1827,8 @@ pf_remove_divert_state(struct pf_state_k
sist->dst.state < TCPS_FIN_WAIT_2) {
pf_set_protostate(sist, PF_PEER_BOTH,
TCPS_TIME_WAIT);
- sist->timeout = PFTM_TCP_CLOSED;
+ pf_update_state_timeout(sist,
+ PFTM_TCP_CLOSED);
sist->expire = getuptime();
}
sist->state_flags |= PFSTATE_INP_UNLINKED;
@@ -5036,18 +5048,18 @@ pf_tcp_track_full(struct pf_pdesc *pd, s
(*stp)->expire = getuptime();
if (src->state >= TCPS_FIN_WAIT_2 &&
dst->state >= TCPS_FIN_WAIT_2)
- (*stp)->timeout = PFTM_TCP_CLOSED;
+ pf_update_state_timeout(*stp, PFTM_TCP_CLOSED);
else if (src->state >= TCPS_CLOSING &&
dst->state >= TCPS_CLOSING)
- (*stp)->timeout = PFTM_TCP_FIN_WAIT;
+ pf_update_state_timeout(*stp, PFTM_TCP_FIN_WAIT);
else if (src->state < TCPS_ESTABLISHED ||
dst->state < TCPS_ESTABLISHED)
- (*stp)->timeout = PFTM_TCP_OPENING;
+ pf_update_state_timeout(*stp, PFTM_TCP_OPENING);
else if (src->state >= TCPS_CLOSING ||
dst->state >= TCPS_CLOSING)
- (*stp)->timeout = PFTM_TCP_CLOSING;
+ pf_update_state_timeout(*stp, PFTM_TCP_CLOSING);
else
- (*stp)->timeout = PFTM_TCP_ESTABLISHED;
+ pf_update_state_timeout(*stp, PFTM_TCP_ESTABLISHED);
/* Fall through to PASS packet */
} else if ((dst->state < TCPS_SYN_SENT ||
@@ -5229,18 +5241,18 @@ pf_tcp_track_sloppy(struct pf_pdesc *pd,
(*stp)->expire = getuptime();
if (src->state >= TCPS_FIN_WAIT_2 &&
dst->state >= TCPS_FIN_WAIT_2)
- (*stp)->timeout = PFTM_TCP_CLOSED;
+ pf_update_state_timeout(*stp, PFTM_TCP_CLOSED);
else if (src->state >= TCPS_CLOSING &&
dst->state >= TCPS_CLOSING)
- (*stp)->timeout = PFTM_TCP_FIN_WAIT;
+ pf_update_state_timeout(*stp, PFTM_TCP_FIN_WAIT);
else if (src->state < TCPS_ESTABLISHED ||
dst->state < TCPS_ESTABLISHED)
- (*stp)->timeout = PFTM_TCP_OPENING;
+ pf_update_state_timeout(*stp, PFTM_TCP_OPENING);
else if (src->state >= TCPS_CLOSING ||
dst->state >= TCPS_CLOSING)
- (*stp)->timeout = PFTM_TCP_CLOSING;
+ pf_update_state_timeout(*stp, PFTM_TCP_CLOSING);
else
- (*stp)->timeout = PFTM_TCP_ESTABLISHED;
+ pf_update_state_timeout(*stp, PFTM_TCP_ESTABLISHED);
return (PF_PASS);
}
@@ -5377,7 +5389,7 @@ pf_test_state(struct pf_pdesc *pd, struc
addlog("\n");
}
/* XXX make sure it's the same direction ?? */
- (*stp)->timeout = PFTM_PURGE;
+ pf_update_state_timeout(*stp, PFTM_PURGE);
pf_state_unref(*stp);
*stp = NULL;
pf_mbuf_link_inpcb(pd->m, inp);
@@ -5417,9 +5429,9 @@ pf_test_state(struct pf_pdesc *pd, struc
(*stp)->expire = getuptime();
if (src->state == PFUDPS_MULTIPLE &&
dst->state == PFUDPS_MULTIPLE)
- (*stp)->timeout = PFTM_UDP_MULTIPLE;
+ pf_update_state_timeout(*stp, PFTM_UDP_MULTIPLE);
else
- (*stp)->timeout = PFTM_UDP_SINGLE;
+ pf_update_state_timeout(*stp, PFTM_UDP_SINGLE);
break;
default:
/* update states */
@@ -5432,9 +5444,9 @@ pf_test_state(struct pf_pdesc *pd, struc
(*stp)->expire = getuptime();
if (src->state == PFOTHERS_MULTIPLE &&
dst->state == PFOTHERS_MULTIPLE)
- (*stp)->timeout = PFTM_OTHER_MULTIPLE;
+ pf_update_state_timeout(*stp, PFTM_OTHER_MULTIPLE);
else
- (*stp)->timeout = PFTM_OTHER_SINGLE;
+ pf_update_state_timeout(*stp, PFTM_OTHER_SINGLE);
break;
}
@@ -5585,7 +5597,7 @@ pf_test_state_icmp(struct pf_pdesc *pd,
return (ret);
(*stp)->expire = getuptime();
- (*stp)->timeout = PFTM_ICMP_ERROR_REPLY;
+ pf_update_state_timeout(*stp, PFTM_ICMP_ERROR_REPLY);
/* translate source/destination address, if necessary */
if ((*stp)->key[PF_SK_WIRE] != (*stp)->key[PF_SK_STACK]) {