Hello,

On Sat, Nov 25, 2023 at 10:49:44AM +0100, j...@navratil.cz 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
>                        
> r...@syspatch-74-amd64.openbsd.org:/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]) {

Reply via email to