aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2025-03-27 14:21:41 +0000
committerKristof Provost <kp@FreeBSD.org>2025-03-31 12:55:42 +0000
commit8efd2acf07bc0e1c3ea1f7390e0f1cfb7cf6f86c (patch)
treeb0e1f1b5b60780011bb115e9d50301226e0419af
parent2ad0f7e91582dde5475ceb1a1942930549e5c628 (diff)
pf: improve pf_state_key_attach() error handling
If we fail to attach the stack key that means we've already attached the wire key. That means the state could be found by other cores, and given that we then free it, be used after free. Fix this by not releasing the ID hashrow lock and key locks until after we've removed the inserted key again, ensuring the state cannot be found by other cores. Reported by: markj Submitted by: glebius Reviewed by: glebius, markj MFC after: 3 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D49550
-rw-r--r--sys/netpfil/pf/pf.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index ef86d70db760..ae1ad679d951 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -1523,15 +1523,28 @@ keyattach:
printf("\n");
}
s->timeout = PFTM_UNLINKED;
+ if (idx == PF_SK_STACK)
+ /*
+ * Remove the wire key from
+ * the hash. Other threads
+ * can't be referencing it
+ * because we still hold the
+ * hash lock.
+ */
+ pf_state_key_detach(s,
+ PF_SK_WIRE);
PF_HASHROW_UNLOCK(ih);
KEYS_UNLOCK();
- if (idx == PF_SK_WIRE) {
+ if (idx == PF_SK_WIRE)
+ /*
+ * We've not inserted either key.
+ * Free both.
+ */
uma_zfree(V_pf_state_key_z, skw);
- if (skw != sks)
- uma_zfree(V_pf_state_key_z, sks);
- } else {
- pf_detach_state(s);
- }
+ if (skw != sks)
+ uma_zfree(
+ V_pf_state_key_z,
+ sks);
return (EEXIST); /* collision! */
}
}