java-topology/defects/openbsd/patch/openbsd-0002-ifa-ifwithaddr-nested-scan.patch

84 lines
2.4 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000200
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -370,6 +370,10 @@ int if_setlladdr(struct ifnet *, const uint8_t *);
struct ifaddr *if_get_gwaddr(struct ifnet *, sa_family_t);
struct ifaddr *ifa_ifwithaddr(const struct sockaddr *, u_int);
struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *, u_int);
+/* CWE-407: hash-based local-address lookup maintenance */
+void ifa_hash_insert(struct ifaddr *);
+void ifa_hash_remove(struct ifaddr *);
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -60,6 +60,24 @@
#include <net/if_var.h>
#include <net/route.h>
+/*
+ * CWE-407 fix: per-rdomain hash table for O(1) local-address lookup.
+ * Replaces O(I×A) double-foreach in ifa_ifwithaddr.
+ * Hash key: (sa_family XOR first 4 bytes of sa_data).
+ */
+#define IFA_HASH_BITS 8
+#define IFA_HASH_SIZE (1 << IFA_HASH_BITS)
+#define IFA_HASH_MASK (IFA_HASH_SIZE - 1)
+
+static inline unsigned int
+ifa_hash_key(const struct sockaddr *sa)
+{
+ const u_int8_t *d = (const u_int8_t *)sa->sa_data;
+ unsigned int h = sa->sa_family;
+ if (sa->sa_len > offsetof(struct sockaddr, sa_data) + 3)
+ h ^= (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+ return h & IFA_HASH_MASK;
+}
+
+LIST_HEAD(ifa_hash_bucket, ifaddr);
+static struct ifa_hash_bucket ifa_hashtbl[IFA_HASH_SIZE];
+
+void
+ifa_hash_insert(struct ifaddr *ifa)
+{
+ unsigned int h = ifa_hash_key(ifa->ifa_addr);
+ LIST_INSERT_HEAD(&ifa_hashtbl[h], ifa, ifa_hash);
+}
+
+void
+ifa_hash_remove(struct ifaddr *ifa)
+{
+ LIST_REMOVE(ifa, ifa_hash);
+}
+
#define equal(a1, a2) \
(bcmp((caddr_t)(a1), (caddr_t)(a2), \
(a1)->sa_len) == 0)
@@ -1619,22 +1642,19 @@ ifa_ifwithaddr(const struct sockaddr *addr, u_int rtableid)
{
- struct ifnet *ifp;
struct ifaddr *ifa;
u_int rdomain;
NET_ASSERT_LOCKED();
rdomain = rtable_l2(rtableid);
- TAILQ_FOREACH(ifp, &ifnetlist, if_list) { /* O(I) */
- if (ifp->if_rdomain != rdomain)
- continue;
- TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { /* O(A) */
- if (ifa->ifa_addr->sa_family != addr->sa_family)
- continue;
- if (equal(addr, ifa->ifa_addr)) {
- return (ifa);
- }
+ /* CWE-407: O(1) hash lookup instead of O(I×A) nested scan */
+ LIST_FOREACH(ifa, &ifa_hashtbl[ifa_hash_key(addr)], ifa_hash) {
+ if (ifa->ifa_ifp->if_rdomain != rdomain)
+ continue;
+ if (ifa->ifa_addr->sa_family != addr->sa_family)
+ continue;
+ if (equal(addr, ifa->ifa_addr)) {
+ return (ifa);
}
}
return (NULL);