git: b951994eddd4 - main - pf: Set the reassembly flags under the rules lock

From: R. Christian McDonald <rcm_at_FreeBSD.org>
Date: Tue, 13 Oct 2026 13:40:24 UTC
The branch main has been updated by rcm:

URL: https://cgit.FreeBSD.org/src/commit/?id=b951994eddd4d274514df751da06680a32139037

commit b951994eddd4d274514df751da06680a32139037
Author:     R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-10-13 13:39:30 +0000
Commit:     R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-13 13:39:30 +0000

    pf: Set the reassembly flags under the rules lock
    
    DIOCSETREASS stored V_pf_status.reass twice with no lock, first the
    flags it was given and then, if reassembly was not among them, zero.
    pf_normalize_ip() and pf_normalize_ip6() read the flags with the rules
    lock held for reading, so a packet could see the intermediate value.
    Compute the flags first and store them once, with the rules lock held
    for writing, as DIOCSETDEBUG and DIOCSETHOSTID do.
    
    Reviewed by:            kp
    Fixes:                  39282ef356db ("pf: backport OpenBSD syntax of "scrub" option for "match" and "pass" rules")
    MFC after:              2 weeks
    Sponsored by:           Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D60531
---
 sys/netpfil/pf/pf_ioctl.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 095d357b5ef5..f673d3b4cf1e 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -6627,12 +6627,16 @@ DIOCCHANGEADDR_error:
 
 	case DIOCSETREASS: {
 		u_int32_t	*reass = (u_int32_t *)addr;
+		u_int32_t	 flags;
 
-		V_pf_status.reass = *reass & (PF_REASS_ENABLED|PF_REASS_NODF);
+		flags = *reass & (PF_REASS_ENABLED|PF_REASS_NODF);
 		/* Removal of DF flag without reassembly enabled is not a
 		 * valid combination. Disable reassembly in such case. */
-		if (!(V_pf_status.reass & PF_REASS_ENABLED))
-			V_pf_status.reass = 0;
+		if (!(flags & PF_REASS_ENABLED))
+			flags = 0;
+		PF_RULES_WLOCK();
+		V_pf_status.reass = flags;
+		PF_RULES_WUNLOCK();
 		break;
 	}