git: ff80dd034a8c - main - pf: fix DIOCCHANGERULE after pf config and rb tree of rules

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Tue, 10 May 2022 21:17:06 UTC
The branch main has been updated by mjg:

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

commit ff80dd034a8ca73274b7861e1b3fc801c837a385
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2022-05-04 19:53:12 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2022-05-10 21:16:47 +0000

    pf: fix DIOCCHANGERULE after pf config and rb tree of rules
    
    Reviewed by:    kp
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_ioctl.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 65839d1d31d9..6b8d63b8bdce 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -3432,6 +3432,7 @@ DIOCGETRULENV_error:
 		}
 #define	ERROUT(x)	ERROUT_IOCTL(DIOCCHANGERULE_error, x)
 
+		PF_CONFIG_LOCK();
 		PF_RULES_WLOCK();
 #ifdef PF_WANT_32_TO_64_COUNTER
 		if (newrule != NULL) {
@@ -3540,6 +3541,7 @@ DIOCGETRULENV_error:
 			if (error) {
 				pf_free_rule(newrule);
 				PF_RULES_WUNLOCK();
+				PF_CONFIG_UNLOCK();
 				break;
 			}
 
@@ -3562,6 +3564,7 @@ DIOCGETRULENV_error:
 				if (newrule != NULL)
 					pf_free_rule(newrule);
 				PF_RULES_WUNLOCK();
+				PF_CONFIG_UNLOCK();
 				error = EINVAL;
 				break;
 			}
@@ -3570,8 +3573,20 @@ DIOCGETRULENV_error:
 		if (pcr->action == PF_CHANGE_REMOVE) {
 			pf_unlink_rule(ruleset->rules[rs_num].active.ptr,
 			    oldrule);
+			RB_REMOVE(pf_krule_global,
+			    ruleset->rules[rs_num].active.tree, oldrule);
 			ruleset->rules[rs_num].active.rcount--;
 		} else {
+			pf_hash_rule(newrule);
+			if (RB_INSERT(pf_krule_global,
+			    ruleset->rules[rs_num].active.tree, newrule) != NULL) {
+				pf_free_rule(newrule);
+				PF_RULES_WUNLOCK();
+				PF_CONFIG_UNLOCK();
+				error = EEXIST;
+				break;
+			}
+
 			if (oldrule == NULL)
 				TAILQ_INSERT_TAIL(
 				    ruleset->rules[rs_num].active.ptr,
@@ -3597,6 +3612,7 @@ DIOCGETRULENV_error:
 		pf_remove_if_empty_kruleset(ruleset);
 
 		PF_RULES_WUNLOCK();
+		PF_CONFIG_UNLOCK();
 		break;
 
 #undef ERROUT