java-topology/defects/nfs-utils-0001/patch/nfs-utils-0001.patch

117 lines
3 KiB
Diff

# UNDF: UNDF-2026-000001021
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -1,5 +1,6 @@
/*
* support/export/client.c
+ * CWE-407: client_lookup non-FQDN branch O(N) scan per call = O(N^2) total
*
* Maintain list of nfsd clients.
*
@@ -22,6 +23,7 @@
#include "sockaddr.h"
#include "misc.h"
+#include "search.h" /* hsearch_r: POSIX hash table */
#include "nfslib.h"
#include "exportfs.h"
@@ -33,6 +35,31 @@ extern int innetgr(char *netgr, char *host, char *, char *);
static char *add_name(char *old, const char *add);
nfs_client *clientlist[MCL_MAXTYPES] = { NULL, };
+/*
+ * Hash table for O(1) hostname lookup of non-FQDN clients.
+ * Keyed by lowercased hostname string, value is nfs_client pointer.
+ * Sized for up to 8192 unique non-FQDN clients (wildcards, netgroups,
+ * subnets, GSS identifiers). Resized on overflow would be ideal but
+ * POSIX hsearch_r does not support resize, so we pre-allocate large.
+ *
+ * This replaces the O(N) linked list scan in client_lookup for
+ * non-FQDN types, reducing export_read from O(N^2) to O(N).
+ */
+#define CLIENT_HT_SIZE 8192
+static struct hsearch_data client_ht;
+static int client_ht_initialized = 0;
+
+static void client_ht_init(void)
+{
+ if (!client_ht_initialized) {
+ memset(&client_ht, 0, sizeof(client_ht));
+ hcreate_r(CLIENT_HT_SIZE, &client_ht);
+ client_ht_initialized = 1;
+ }
+}
+
+/* Forward declaration */
+static nfs_client *client_ht_lookup(const char *hname);
+static void client_ht_insert(nfs_client *clp);
static void
@@ -286,11 +313,13 @@ client_lookup(char *hname, int canonical)
if (client_check(clp, ai))
break;
} else {
- for (clp = clientlist[htype]; clp; clp = clp->m_next) {
- if (strcasecmp(hname, clp->m_hostname)==0)
- break;
- }
+ /*
+ * Use hash table for O(1) lookup instead of O(N) linked
+ * list scan. With many netgroup/wildcard/subnet entries,
+ * the old code was O(N^2) over all export_create calls.
+ */
+ clp = client_ht_lookup(hname);
}
if (clp == NULL) {
@@ -302,6 +331,8 @@ client_lookup(char *hname, int canonical)
clp = NULL;
goto out;
}
+ if (htype != MCL_FQDN)
+ client_ht_insert(clp);
client_add(clp);
}
@@ -360,9 +391,44 @@ client_freeall(void)
while (*head) {
*head = (clp = *head)->m_next;
client_free(clp);
}
}
+ /* Destroy and reinitialize hash table */
+ if (client_ht_initialized) {
+ hdestroy_r(&client_ht);
+ client_ht_initialized = 0;
+ }
+}
+
+static nfs_client *client_ht_lookup(const char *hname)
+{
+ ENTRY item, *found;
+
+ client_ht_init();
+ item.key = (char *)hname;
+ item.data = NULL;
+
+ if (hsearch_r(item, FIND, &found, &client_ht) != 0)
+ return (nfs_client *)found->data;
+ return NULL;
+}
+
+static void client_ht_insert(nfs_client *clp)
+{
+ ENTRY item, *found;
+
+ client_ht_init();
+ item.key = clp->m_hostname;
+ item.data = clp;
+
+ /* hsearch_r with ENTER will insert if not found */
+ hsearch_r(item, ENTER, &found, &client_ht);
}
/**
* client_resolve - look up an IP address