new file mode 100644
@@ -0,0 +1,245 @@
+From fa3ea0362354af7370abb5fe8c6f31a32a73af8e Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Mon, 28 Sep 2026 14:27:16 +0200
+Subject: [PATCH] CVE-2026-89092: nscd: replace alloca with malloc in aicache,
+ hstcache
+
+This changes the alloca fallback to a malloc fallback
+in the addrinfo and host cache code.
+
+This fixes bug 34624.
+
+Co-authored-by: Florian Weimer <fweimer@redhat.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+(cherry picked from commit cbf59b836645b6ac69ad8c47a560598bc4942ecc)
+
+CVE: CVE-2026-89092
+Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=fa3ea0362354af7370abb5fe8c6f31a32a73af8e]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ nscd/aicache.c | 27 ++++++++++++++++++---------
+ nscd/hstcache.c | 47 ++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 52 insertions(+), 22 deletions(-)
+
+diff --git a/nscd/aicache.c b/nscd/aicache.c
+index 6f47236627..1ac86b86d8 100644
+--- a/nscd/aicache.c
++++ b/nscd/aicache.c
+@@ -93,7 +93,9 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
+ int32_t ttl = INT32_MAX;
+ ssize_t total = 0;
+ char *key_copy = NULL;
+- bool alloca_used = false;
++ /* If not NULL, dataset is a temporary dataset not inserted into the
++ database, and needs to be free'd. */
++ void *dataset_alloc = NULL;
+ time_t timeout = MAX_TIMEOUT_VALUE;
+
+ while (!no_more)
+@@ -164,10 +166,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
+ /* We cannot permanently add the result in the moment. But
+ we can provide the result as is. Store the data in some
+ temporary memory. */
+- dataset = (struct dataset *) alloca (total + req->key_len);
++ dataset = (struct dataset *) malloc (total + req->key_len);
++ if (dataset == NULL)
++ goto out;
+
+ /* We cannot add this record to the permanent database. */
+- alloca_used = true;
++ dataset_alloc = dataset;
+ }
+
+ /* Fill in the address and address families. */
+@@ -336,10 +340,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
+ /* We cannot permanently add the result in the moment. But
+ we can provide the result as is. Store the data in some
+ temporary memory. */
+- dataset = (struct dataset *) alloca (total + req->key_len);
++ dataset = (struct dataset *) malloc (total + req->key_len);
++ if (dataset == NULL)
++ goto out;
+
+ /* We cannot add this record to the permanent database. */
+- alloca_used = true;
++ dataset_alloc = dataset;
+ }
+
+ /* Fill in the address and address families. */
+@@ -391,8 +397,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
+ resp)) == 0)
+ {
+ /* The data has not changed. We will just bump the
+- timeout value. Note that the new record has been
+- allocated on the stack and need not be freed. */
++ timeout value. */
+ dh->timeout = dataset->head.timeout;
+ dh->ttl = dataset->head.ttl;
+ ++dh->nreloads;
+@@ -410,7 +415,9 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
+
+ dataset = memcpy (newp, dataset, total + req->key_len);
+- alloca_used = false;
++
++ free (dataset_alloc);
++ dataset_alloc = NULL;
+ }
+
+ /* Mark the old record as obsolete. */
+@@ -488,7 +495,7 @@ next_nip:
+ out:
+ __resolv_context_put (ctx);
+
+- if (dataset != NULL && !alloca_used)
++ if (dataset != NULL && dataset_alloc == NULL)
+ {
+ /* If necessary, we also propagate the data to disk. */
+ if (db->persistent)
+@@ -514,6 +521,8 @@ next_nip:
+ scratch_buffer_free (&tmpbuf4);
+ scratch_buffer_free (&canonbuf);
+
++ free (dataset_alloc);
++
+ return timeout;
+ }
+
+diff --git a/nscd/hstcache.c b/nscd/hstcache.c
+index 7b3a8ab1ea..11af5cb34a 100644
+--- a/nscd/hstcache.c
++++ b/nscd/hstcache.c
+@@ -15,7 +15,6 @@
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
+
+-#include <alloca.h>
+ #include <assert.h>
+ #include <errno.h>
+ #include <error.h>
+@@ -187,7 +186,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ /* Determine the I/O structure. */
+ size_t h_name_len = strlen (hst->h_name) + 1;
+ size_t h_aliases_cnt;
+- uint32_t *h_aliases_len;
++ uint32_t *h_aliases_len = NULL;
+ size_t h_addr_list_cnt;
+ char *addresses;
+ char *aliases;
+@@ -201,7 +200,13 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ for (cnt = 0; hst->h_aliases[cnt] != NULL; ++cnt)
+ ++h_aliases_cnt;
+ /* Determine the length of all aliases. */
+- h_aliases_len = (uint32_t *) alloca (h_aliases_cnt * sizeof (uint32_t));
++ if (h_aliases_cnt > 0)
++ {
++ h_aliases_len = (uint32_t *) reallocarray (NULL, h_aliases_cnt,
++ sizeof (uint32_t));
++ if (h_aliases_len == NULL)
++ return MAX_TIMEOUT_VALUE;
++ }
+ total = 0;
+ for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
+ {
+@@ -215,8 +220,11 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ ++h_addr_list_cnt;
+
+ if (h_addr_list_cnt == 0)
+- /* Invalid entry. */
+- return MAX_TIMEOUT_VALUE;
++ {
++ /* Invalid entry. */
++ free (h_aliases_len);
++ return MAX_TIMEOUT_VALUE;
++ }
+
+ total += (sizeof (struct dataset)
+ + h_name_len
+@@ -227,8 +235,10 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ change. Allocate memory on the cache since it is likely
+ discarded anyway. If it turns out to be necessary to have a
+ new record we can still allocate real memory. */
+- bool alloca_used = false;
+ dataset = NULL;
++ /* If not NULL, dataset is a temporary dataset not inserted into
++ the database, and needs to be free'd. */
++ void *dataset_alloc = NULL;
+
+ /* If the record contains more than one IP address (used for
+ load balancing etc) don't cache the entry. This is something
+@@ -244,10 +254,15 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ /* We cannot permanently add the result in the moment. But
+ we can provide the result as is. Store the data in some
+ temporary memory. */
+- dataset = (struct dataset *) alloca (total + req->key_len);
++ dataset = (struct dataset *) malloc (total + req->key_len);
++ if (dataset == NULL)
++ {
++ free (h_aliases_len);
++ return MAX_TIMEOUT_VALUE;
++ }
+
+ /* We cannot add this record to the permanent database. */
+- alloca_used = true;
++ dataset_alloc = dataset;
+ }
+
+ timeout = datahead_init_pos (&dataset->head, total + req->key_len,
+@@ -270,7 +285,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ cp = dataset->strdata;
+
+ cp = mempcpy (cp, hst->h_name, h_name_len);
+- cp = mempcpy (cp, h_aliases_len, h_aliases_cnt * sizeof (uint32_t));
++ if (h_aliases_cnt > 0)
++ cp = mempcpy (cp, h_aliases_len, h_aliases_cnt * sizeof (uint32_t));
+
+ /* The normal addresses first. */
+ addresses = cp;
+@@ -282,6 +298,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
+ cp = mempcpy (cp, hst->h_aliases[cnt], h_aliases_len[cnt]);
+
++ free (h_aliases_len);
++
+ assert (cp
+ == dataset->strdata + total - offsetof (struct dataset,
+ strdata));
+@@ -307,8 +325,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ dh->allocsize - offsetof (struct dataset, resp)) == 0)
+ {
+ /* The data has not changed. We will just bump the
+- timeout value. Note that the new record has been
+- allocated on the stack and need not be freed. */
++ timeout value. */
+ assert (h_addr_list_cnt == 1);
+ dh->ttl = dataset->head.ttl;
+ dh->timeout = dataset->head.timeout;
+@@ -334,7 +351,9 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
+
+ dataset = memcpy (newp, dataset, total + req->key_len);
+- alloca_used = false;
++
++ free (dataset_alloc);
++ dataset_alloc = NULL;
+ }
+ }
+
+@@ -362,7 +381,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+ the current cache handling cannot handle and it is more than
+ questionable whether it is worthwhile complicating the cache
+ handling just for handling such a special case. */
+- if (! alloca_used)
++ if (dataset_alloc == NULL)
+ {
+ /* If necessary, we also propagate the data to disk. */
+ if (db->persistent)
+@@ -393,6 +412,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
+
+ pthread_rwlock_unlock (&db->lock);
+ }
++ free (dataset_alloc);
++ dataset_alloc = NULL;
+ }
+
+ if (__builtin_expect (!all_written, 0) && debug_level > 0)
@@ -79,6 +79,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
file://0044-CVE-2026-86805-CVE-2026-95818-02.patch \
file://0045-CVE-2026-86805-CVE-2026-95818-03.patch \
file://0046-CVE-2026-86805-CVE-2026-95818-04.patch \
+ file://0047-CVE-2026-89092.patch \
"
S = "${WORKDIR}/git"
B = "${WORKDIR}/build-${TARGET_SYS}"