From: Peter Marko <[email protected]>

Pick patch referencing this CVE from 3.41 branch (oldest release
still receiving security updates).

Signed-off-by: Peter Marko <[email protected]>
---
 .../glibc/glibc/0047-CVE-2026-89092.patch     | 245 ++++++++++++++++++
 meta/recipes-core/glibc/glibc_2.39.bb         |   1 +
 2 files changed, 246 insertions(+)
 create mode 100644 meta/recipes-core/glibc/glibc/0047-CVE-2026-89092.patch

diff --git a/meta/recipes-core/glibc/glibc/0047-CVE-2026-89092.patch 
b/meta/recipes-core/glibc/glibc/0047-CVE-2026-89092.patch
new file mode 100644
index 00000000000..8df9dc904e4
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0047-CVE-2026-89092.patch
@@ -0,0 +1,245 @@
+From fa3ea0362354af7370abb5fe8c6f31a32a73af8e Mon Sep 17 00:00:00 2001
+From: DJ Delorie <[email protected]>
+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 <[email protected]>
+Reviewed-by: Adhemerval Zanella <[email protected]>
+(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 <[email protected]>
+---
+ 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)
diff --git a/meta/recipes-core/glibc/glibc_2.39.bb 
b/meta/recipes-core/glibc/glibc_2.39.bb
index d8867bcff9a..66250fbdb2a 100644
--- a/meta/recipes-core/glibc/glibc_2.39.bb
+++ b/meta/recipes-core/glibc/glibc_2.39.bb
@@ -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}"
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#248468): 
https://lists.openembedded.org/g/openembedded-core/message/248468
Mute This Topic: https://lists.openembedded.org/mt/121892964/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to