59 lines
2.1 KiB
Diff
59 lines
2.1 KiB
Diff
# UNDF: UNDF-2026-000000199
|
|
--- a/sys/net/pf_osfp.c
|
|
+++ b/sys/net/pf_osfp.c
|
|
@@ -74,6 +74,14 @@ struct pool pf_osfp_pl;
|
|
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list =
|
|
SLIST_HEAD_INITIALIZER(pf_osfp_list); /* [p] */
|
|
|
|
+/*
|
|
+ * CWE-407 fix: hash pf_osfp_list by fp_tcpopts to replace O(N) linear scan
|
|
+ * in pf_osfp_find with O(N/OSFP_BUCKETS) bucket scan. With N=246 default
|
|
+ * entries and 64 buckets, average bucket depth ~4 instead of 246.
|
|
+ * Reduces pf_osfp_validate from O(N²) to O(N * bucket_depth).
|
|
+ */
|
|
+#define OSFP_BUCKETS 64
|
|
+#define OSFP_HASH(tc) ((unsigned int)((tc) ^ ((tc) >> 8)) % OSFP_BUCKETS)
|
|
+static SLIST_HEAD(pf_osfp_bucket, pf_os_fingerprint) pf_osfp_hash[OSFP_BUCKETS];
|
|
+
|
|
struct pf_os_fingerprint *pf_osfp_find(struct pf_os_fingerprint *,
|
|
u_int8_t);
|
|
struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_os_fingerprint *);
|
|
@@ -294,6 +302,12 @@ pf_osfp_flush(void)
|
|
while ((fp = SLIST_FIRST(&pf_osfp_list))) {
|
|
SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
|
|
pool_put(&pf_osfp_pl, fp);
|
|
+ /* Note: bucket list entries are also removed with the main list.
|
|
+ * Re-init all buckets after flush. */
|
|
+ }
|
|
+ for (int i = 0; i < OSFP_BUCKETS; i++) {
|
|
+ while (!SLIST_EMPTY(&pf_osfp_hash[i]))
|
|
+ SLIST_REMOVE_HEAD(&pf_osfp_hash[i], fp_next);
|
|
}
|
|
}
|
|
|
|
@@ -528,12 +542,15 @@ pf_osfp_find(struct pf_os_fingerprint *find, u_int8_t ttldiff)
|
|
struct pf_os_fingerprint *f;
|
|
|
|
PF_ASSERT_LOCKED();
|
|
+ /* CWE-407: use hash bucket instead of full-list O(N) scan */
|
|
+ unsigned int bucket = OSFP_HASH(find->fp_tcpopts);
|
|
|
|
- SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
|
|
+ SLIST_FOREACH(f, &pf_osfp_hash[bucket], fp_next) {
|
|
if (f->fp_tcpopts != find->fp_tcpopts ||
|
|
... [rest of existing comparison logic unchanged]
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
@@ -556,6 +573,12 @@ pf_osfp_insert(struct pf_os_fingerprint *ins)
|
|
if (prev)
|
|
SLIST_INSERT_AFTER(prev, ins, fp_next);
|
|
else
|
|
SLIST_INSERT_HEAD(&pf_osfp_list, ins, fp_next);
|
|
+
|
|
+ /* CWE-407 fix: also insert into hash bucket for O(1) lookup */
|
|
+ unsigned int bucket = OSFP_HASH(ins->fp_tcpopts);
|
|
+ SLIST_INSERT_HEAD(&pf_osfp_hash[bucket], ins, fp_bucket);
|
|
}
|