git: 6efe8e6be413 - main - pf: Fix a lock leak in pf_ioctl_addrule()

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 28 Jul 2025 15:43:01 UTC
The branch main has been updated by markj:

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

commit 6efe8e6be4135643d8283fcb6773da641326f427
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-07-27 13:23:22 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-07-28 15:40:20 +0000

    pf: Fix a lock leak in pf_ioctl_addrule()
    
    The ERROUT macro assumes that the rules lock is held, but some error
    paths arise before that lock is acquired.  Introduce ERROUT_UNLOCKED for
    that case.
    
    Reviewed by:    kp
    Reported by:    syzkaller
    Fixes:          cc68decda316 ("pf: Reject rules with invalid port ranges")
    Differential Revision:  https://reviews.freebsd.org/D51571
---
 sys/amd64/conf/SYZKALLER  |  5 +++++
 sys/netpfil/pf/pf_ioctl.c | 16 ++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/sys/amd64/conf/SYZKALLER b/sys/amd64/conf/SYZKALLER
new file mode 100644
index 000000000000..49059302793b
--- /dev/null
+++ b/sys/amd64/conf/SYZKALLER
@@ -0,0 +1,5 @@
+include GENERIC
+ident SYZKALLER
+
+options 	COVERAGE
+options 	KCOV
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index ea9f7fe441c6..9abc07c36788 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2092,19 +2092,18 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
 	int			 rs_num;
 	int			 error = 0;
 
-	if ((rule->return_icmp >> 8) > ICMP_MAXTYPE) {
-		error = EINVAL;
-		goto errout_unlocked;
-	}
+#define	ERROUT(x)		ERROUT_FUNCTION(errout, x)
+#define	ERROUT_UNLOCKED(x)	ERROUT_FUNCTION(errout_unlocked, x)
 
-#define	ERROUT(x)	ERROUT_FUNCTION(errout, x)
+	if ((rule->return_icmp >> 8) > ICMP_MAXTYPE)
+		ERROUT_UNLOCKED(EINVAL);
 
 	if ((error = pf_rule_checkaf(rule)))
-		ERROUT(error);
+		ERROUT_UNLOCKED(error);
 	if (pf_validate_range(rule->src.port_op, rule->src.port))
-		ERROUT(EINVAL);
+		ERROUT_UNLOCKED(EINVAL);
 	if (pf_validate_range(rule->dst.port_op, rule->dst.port))
-		ERROUT(EINVAL);
+		ERROUT_UNLOCKED(EINVAL);
 
 	if (rule->ifname[0])
 		kif = pf_kkif_create(M_WAITOK);
@@ -2294,6 +2293,7 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
 	return (0);
 
 #undef ERROUT
+#undef ERROUT_UNLOCKED
 errout:
 	PF_RULES_WUNLOCK();
 	PF_CONFIG_UNLOCK();