On Tue, Sep 29, 2026 at 10:02:25PM +0200, Alexandr Nedvedicky wrote:
> Hello,
>
>
> On Mon, Sep 28, 2026 at 11:07:44AM +0200, alf wrote:
> </snip>
> >
> > output of screenshots of the vultr console parsed by OCR
> > and hand edited by me:
> > o8 0 0 0
> > 110011557 41e622,, 0, 1 ) - > e
> > 1kernel: page fault trap, code=0 ,
> > Stopped at rn_match+0x44: movzbl 0(%rdi,%rax,1),%eax
> > TID PID UID PRfLAGS PFLAGS CPU COMMAND
> > 477789 49437 0 0x14000 0x200 0 softnet1
> > *425356 21547 0 0x14000 0x200 2 softnet0
> > rn_match(ffff80003165d010,ffff800000c3f600) at rn_match+0x44
> > pfr_lookup_addr(ffff800016fdcfc0,ffff80003165d0e8,1) at pfr_lookup_addr+0xfb
> > pfr_insert_kentry(ffff800016fdcfc0,ffff80003165d0e8,6a8f74d8) at
> > pfr_insert_ken
> > try+0x32
> > pff_src_connlimit(ffff80003165d3f0) at pf_src_connlimit+0x20a
> > pff_tcp_track_full(ffff80003165d300,ffff80003165d3f0,ffff80003165d3fe,ffff800031
> > 65d254,0) at pf_tcp_track_full+0xcbc
> > pf_test_state(ffff80003165d300,ffff80003165d3f0,ffff80003165d3fe) at
> > pf_test_st
> > ate+0xb03
> > pf_test(18,1,ffff800000057858,ffff80003165d578) at pf_test+0xfcd
> > ip6_input_if(ffff80003165d578,ffff80003165d584,29,0,ffff800000057858,fffffff82
> > bb4358) at ip6_input_if+0x1e9
> > ipv6_input(ffff800000057858,fffffd80be095400,ffffffff82bb4358) at
> > ipv6_input+0x
> > 42
>
> the problem is pf(4) updates overload table without holding a PF_LOCK().
> pf(4) holds state lock to find state, then it grabs reference and drops
> the
> state lock. however if state is created on behalf of rule with overload
> action, pf(4) must lock PF_LOCK() and eventually state table when calling
> to pf_src_connlimit().
>
> patch below should help to make your firewall stable.
>
> I tested the change with rules as follows:
>
> table <minute>
>
> pass all
>
> block in on vio2
> block return in quick on vio2 from <minute> to any
> pass in on vio2 from 10.188.212.0/24 to any keep state (max-src-conn-rate
> 1/1, overload <minute>)
>
>
> thanks for very helpful bug report. hope the patch below will help you.
>
> regards
> sashan
Thanks,
I backported (it didn't like the first hunk) the patch to 7.9-STABLE since
that's
what we're running here, built and installed a new kernel and enabled
rate-limiting
again.
I'll report back how it goes,
Alf
>
> --------8<---------------8<---------------8<------------------8<--------
> diff --git a/sys/net/pf.c b/sys/net/pf.c
> index b465a77b487..e6c67842a07 100644
> --- a/sys/net/pf.c
> +++ b/sys/net/pf.c
> @@ -757,9 +757,12 @@ pf_src_connlimit(struct pf_state **stp)
> int bad = 0;
> struct pf_src_node *sn;
> u_int32_t sn_conn;
> + int rv = 0;
> +
> + PF_LOCK();
>
> if ((sn = pf_get_src_node((*stp), PF_SN_NONE)) == NULL)
> - return (0);
> + goto done;
>
> /*
> * Note: conn limit is bumped on SYN_SENT->ESTBLISHED
> @@ -784,7 +787,7 @@ pf_src_connlimit(struct pf_state **stp)
> }
>
> if (!bad)
> - return (0);
> + goto done;
>
> if ((*stp)->rule.ptr->overload_tbl) {
> struct pfr_addr p;
> @@ -822,6 +825,7 @@ pf_src_connlimit(struct pf_state **stp)
> struct pf_state *st;
>
> pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
> + PF_STATE_ENTER_READ();
> RBT_FOREACH(st, pf_state_tree_id, &tree_id) {
> sk = st->key[PF_SK_WIRE];
> /*
> @@ -844,6 +848,7 @@ pf_src_connlimit(struct pf_state **stp)
> killed++;
> }
> }
> + PF_STATE_EXIT_READ();
> if (pf_status.debug >= LOG_NOTICE)
> addlog(", %u states killed", killed);
> }
> @@ -854,7 +859,12 @@ pf_src_connlimit(struct pf_state **stp)
> /* kill this state */
> pf_update_state_timeout(*stp, PFTM_PURGE);
> pf_set_protostate(*stp, PF_PEER_BOTH, TCPS_CLOSED);
> - return (1);
> +
> + rv = 1;
> +done:
> + PF_UNLOCK();
> +
> + return (rv);
> }
>
> int
>