From 9651e7c5debf11cbc3b53f4c1228428fb11b3cb8 Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Fri, 7 Jun 2024 15:38:58 +0200 Subject: [PATCH] Sync with upstream branch release/2.39/master Upstream commit: fd658f026f25cf59e8db243bc3b3e09cd5a20ba0 nscd is currently not build, so the security fixes below are not relevant. - elf: Also compile dl-misc.os with $(rtld-early-cflags) - CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680) - CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678) - CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678) - CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677) - x86: Define MINIMUM_X86_ISA_LEVEL in config.h [BZ #31676] Related: RHEL-31738 - i386: ulp update for SSE2 --disable-multi-arch configurations - nptl: Fix tst-cancel30 on kernels without ppoll_time64 support Related: RHEL-35602 Fedora 40 commit: 94914be52fd61dacfeb2fe1a27b3741545093a36 --- glibc-upstream-2.39-32.patch | 49 +++++ glibc-upstream-2.39-33.patch | 20 ++ glibc-upstream-2.39-34.patch | 89 ++++++++ glibc-upstream-2.39-35.patch | 32 +++ glibc-upstream-2.39-36.patch | 53 +++++ glibc-upstream-2.39-37.patch | 54 +++++ glibc-upstream-2.39-38.patch | 384 +++++++++++++++++++++++++++++++++++ glibc-upstream-2.39-39.patch | 49 +++++ glibc.spec | 23 ++- 9 files changed, 752 insertions(+), 1 deletion(-) create mode 100644 glibc-upstream-2.39-32.patch create mode 100644 glibc-upstream-2.39-33.patch create mode 100644 glibc-upstream-2.39-34.patch create mode 100644 glibc-upstream-2.39-35.patch create mode 100644 glibc-upstream-2.39-36.patch create mode 100644 glibc-upstream-2.39-37.patch create mode 100644 glibc-upstream-2.39-38.patch create mode 100644 glibc-upstream-2.39-39.patch diff --git a/glibc-upstream-2.39-32.patch b/glibc-upstream-2.39-32.patch new file mode 100644 index 0000000..f5cf970 --- /dev/null +++ b/glibc-upstream-2.39-32.patch @@ -0,0 +1,49 @@ +commit e828914cf9f2fc2caa5bced0fc6a03cb78324979 +Author: Florian Weimer +Date: Tue Apr 23 21:16:32 2024 +0200 + + nptl: Fix tst-cancel30 on kernels without ppoll_time64 support + + Fall back to ppoll if ppoll_time64 fails with ENOSYS. + Fixes commit 370da8a121c3ba9eeb2f13da15fc0f21f4136b25 ("nptl: Fix + tst-cancel30 on sparc64"). + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit f4724843ada64a51d66f65d3199fe431f9d4c254) + +diff --git a/sysdeps/pthread/tst-cancel30.c b/sysdeps/pthread/tst-cancel30.c +index 3030660e5fd93e2c..94ad6281bcf080f4 100644 +--- a/sysdeps/pthread/tst-cancel30.c ++++ b/sysdeps/pthread/tst-cancel30.c +@@ -18,6 +18,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -46,13 +47,19 @@ tf (void *arg) + + /* Wait indefinitely for cancellation, which only works if asynchronous + cancellation is enabled. */ +-#if defined SYS_ppoll || defined SYS_ppoll_time64 +-# ifndef SYS_ppoll_time64 +-# define SYS_ppoll_time64 SYS_ppoll ++#ifdef SYS_ppoll_time64 ++ long int ret = syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL); ++ (void) ret; ++# ifdef SYS_ppoll ++ if (ret == -1 && errno == ENOSYS) ++ syscall (SYS_ppoll, NULL, 0, NULL, NULL); + # endif +- syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL); + #else ++# ifdef SYS_ppoll ++ syscall (SYS_ppoll, NULL, 0, NULL, NULL); ++# else + for (;;); ++# endif + #endif + + return 0; diff --git a/glibc-upstream-2.39-33.patch b/glibc-upstream-2.39-33.patch new file mode 100644 index 0000000..a13dbfa --- /dev/null +++ b/glibc-upstream-2.39-33.patch @@ -0,0 +1,20 @@ +commit e701c7d761f6e5c48d8e9dd5da88cbe2e94943f4 +Author: Florian Weimer +Date: Thu Apr 25 12:56:48 2024 +0200 + + i386: ulp update for SSE2 --disable-multi-arch configurations + + (cherry picked from commit 3a3a4497421422aa854c855cbe5110ca7d598ffc) + +diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps +index 84e6686eba5fe79a..f2139fc172ceef7b 100644 +--- a/sysdeps/i386/fpu/libm-test-ulps ++++ b/sysdeps/i386/fpu/libm-test-ulps +@@ -1232,6 +1232,7 @@ ldouble: 6 + + Function: "hypot": + double: 1 ++float: 1 + float128: 1 + ldouble: 1 + diff --git a/glibc-upstream-2.39-34.patch b/glibc-upstream-2.39-34.patch new file mode 100644 index 0000000..961fedd --- /dev/null +++ b/glibc-upstream-2.39-34.patch @@ -0,0 +1,89 @@ +commit 2f8f157eb0cc7f1d8d9a3fcaa8c55bed53b092a8 +Author: H.J. Lu +Date: Tue Apr 23 13:59:50 2024 -0700 + + x86: Define MINIMUM_X86_ISA_LEVEL in config.h [BZ #31676] + + Define MINIMUM_X86_ISA_LEVEL at configure time to avoid + + /usr/bin/ld: …/build/elf/librtld.os: in function `init_cpu_features': + …/git/elf/../sysdeps/x86/cpu-features.c:1202: undefined reference to `_dl_runtime_resolve_fxsave' + /usr/bin/ld: …/build/elf/librtld.os: relocation R_X86_64_PC32 against undefined hidden symbol `_dl_runtime_resolve_fxsave' can not be used when making a shared object + /usr/bin/ld: final link failed: bad value + collect2: error: ld returned 1 exit status + + when glibc is built with -march=x86-64-v3 and configured with + --with-rtld-early-cflags=-march=x86-64, which is used to allow ld.so to + print an error message on unsupported CPUs: + + Fatal glibc error: CPU does not support x86-64-v3 + + This fixes BZ #31676. + Reviewed-by: Sunil K Pandey + + (cherry picked from commit 46c999741340ea559784c20a45077955b50aca43) + +diff --git a/config.h.in b/config.h.in +index 4d33c63a841d3d6d..1e647de58580bc2d 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -286,6 +286,9 @@ + /* Define if x86 ISA level should be included in shared libraries. */ + #undef INCLUDE_X86_ISA_LEVEL + ++/* The x86 ISA level. 1 for baseline. Undefined on non-x86. */ ++#undef MINIMUM_X86_ISA_LEVEL ++ + /* Define if -msahf is enabled by default on x86. */ + #undef HAVE_X86_LAHF_SAHF + +diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure +index 2a5421bb31e9efe4..d28d9bcb296c6380 100644 +--- a/sysdeps/x86/configure ++++ b/sysdeps/x86/configure +@@ -151,6 +151,13 @@ printf "%s\n" "$libc_cv_have_x86_isa_level" >&6; } + else + libc_cv_have_x86_isa_level=baseline + fi ++if test $libc_cv_have_x86_isa_level = baseline; then ++ printf "%s\n" "#define MINIMUM_X86_ISA_LEVEL 1" >>confdefs.h ++ ++else ++ printf "%s\n" "#define MINIMUM_X86_ISA_LEVEL $libc_cv_have_x86_isa_level" >>confdefs.h ++ ++fi + config_vars="$config_vars + have-x86-isa-level = $libc_cv_have_x86_isa_level" + config_vars="$config_vars +diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac +index 78ff7c8f41c552bc..5b0acd03d2a30c9b 100644 +--- a/sysdeps/x86/configure.ac ++++ b/sysdeps/x86/configure.ac +@@ -105,6 +105,11 @@ EOF + else + libc_cv_have_x86_isa_level=baseline + fi ++if test $libc_cv_have_x86_isa_level = baseline; then ++ AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, 1) ++else ++ AC_DEFINE_UNQUOTED(MINIMUM_X86_ISA_LEVEL, $libc_cv_have_x86_isa_level) ++fi + LIBC_CONFIG_VAR([have-x86-isa-level], [$libc_cv_have_x86_isa_level]) + LIBC_CONFIG_VAR([x86-isa-level-3-or-above], [3 4]) + LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level]) +diff --git a/sysdeps/x86/isa-level.h b/sysdeps/x86/isa-level.h +index 11fe1ca90c5bfedf..2c7f74212b9a27e5 100644 +--- a/sysdeps/x86/isa-level.h ++++ b/sysdeps/x86/isa-level.h +@@ -61,8 +61,10 @@ + # define __X86_ISA_V4 0 + #endif + +-#define MINIMUM_X86_ISA_LEVEL \ ++#ifndef MINIMUM_X86_ISA_LEVEL ++# define MINIMUM_X86_ISA_LEVEL \ + (__X86_ISA_V1 + __X86_ISA_V2 + __X86_ISA_V3 + __X86_ISA_V4) ++#endif + + /* Depending on the minimum ISA level, a feature check result can be a + compile-time constant.. */ diff --git a/glibc-upstream-2.39-35.patch b/glibc-upstream-2.39-35.patch new file mode 100644 index 0000000..41555b4 --- /dev/null +++ b/glibc-upstream-2.39-35.patch @@ -0,0 +1,32 @@ +commit 1263d583d2e28afb8be53f8d6922f0842036f35d +Author: Florian Weimer +Date: Thu Apr 25 15:00:45 2024 +0200 + + CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677) + + Using alloca matches what other caches do. The request length is + bounded by MAXKEYLEN. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa) + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 0c6e46f15c5d7139..f227dc7fa2856e38 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -502,12 +502,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + = (struct indataset *) mempool_alloc (db, + sizeof (*dataset) + req->key_len, + 1); +- struct indataset dataset_mem; + bool cacheable = true; + if (__glibc_unlikely (dataset == NULL)) + { + cacheable = false; +- dataset = &dataset_mem; ++ /* The alloca is safe because nscd_run_worker verfies that ++ key_len is not larger than MAXKEYLEN. */ ++ dataset = alloca (sizeof (*dataset) + req->key_len); + } + + datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, diff --git a/glibc-upstream-2.39-36.patch b/glibc-upstream-2.39-36.patch new file mode 100644 index 0000000..2851845 --- /dev/null +++ b/glibc-upstream-2.39-36.patch @@ -0,0 +1,53 @@ +commit 5a508e0b508c8ad53bd0d2fb48fd71b242626341 +Author: Florian Weimer +Date: Thu Apr 25 15:01:07 2024 +0200 + + CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678) + + If we failed to add a not-found response to the cache, the dataset + point can be null, resulting in a null pointer dereference. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa) + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index f227dc7fa2856e38..c18fe111f37496d7 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -147,7 +147,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + /* No such service. */ + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, + &key_copy); +- goto writeout; ++ goto maybe_cache_add; + } + + memset (&data, '\0', sizeof (data)); +@@ -348,7 +348,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + { + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, + &key_copy); +- goto writeout; ++ goto maybe_cache_add; + } + + total = buffilled; +@@ -410,14 +410,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + if (he == NULL && fd != -1) +- { +- /* We write the dataset before inserting it to the database +- since while inserting this thread might block and so would +- unnecessarily let the receiver wait. */ +- writeout: ++ /* We write the dataset before inserting it to the database since ++ while inserting this thread might block and so would ++ unnecessarily let the receiver wait. */ + writeall (fd, &dataset->resp, dataset->head.recsize); +- } + ++ maybe_cache_add: + if (cacheable) + { + /* If necessary, we also propagate the data to disk. */ diff --git a/glibc-upstream-2.39-37.patch b/glibc-upstream-2.39-37.patch new file mode 100644 index 0000000..b0a31a8 --- /dev/null +++ b/glibc-upstream-2.39-37.patch @@ -0,0 +1,54 @@ +commit c99f886de54446cd4447db6b44be93dabbdc2f8b +Author: Florian Weimer +Date: Thu Apr 25 15:01:07 2024 +0200 + + CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678) + + The addgetnetgrentX call in addinnetgrX may have failed to produce + a result, so the result variable in addinnetgrX can be NULL. + Use db->negtimeout as the fallback value if there is no result data; + the timeout is also overwritten below. + + Also avoid sending a second not-found response. (The client + disconnects after receiving the first response, so the data stream did + not go out of sync even without this fix.) It is still beneficial to + add the negative response to the mapping, so that the client can get + it from there in the future, instead of going through the socket. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit b048a482f088e53144d26a61c390bed0210f49f2) + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index c18fe111f37496d7..e22ffa5884e36260 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -511,14 +511,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + + datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, + sizeof (innetgroup_response_header), +- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl); ++ he == NULL ? 0 : dh->nreloads + 1, ++ result == NULL ? db->negtimeout : result->head.ttl); + /* Set the notfound status and timeout based on the result from + getnetgrent. */ +- dataset->head.notfound = result->head.notfound; ++ dataset->head.notfound = result == NULL || result->head.notfound; + dataset->head.timeout = timeout; + + dataset->resp.version = NSCD_VERSION; +- dataset->resp.found = result->resp.found; ++ dataset->resp.found = result != NULL && result->resp.found; + /* Until we find a matching entry the result is 0. */ + dataset->resp.result = 0; + +@@ -566,7 +567,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + goto out; + } + +- if (he == NULL) ++ /* addgetnetgrentX may have already sent a notfound response. Do ++ not send another one. */ ++ if (he == NULL && dataset->resp.found) + { + /* We write the dataset before inserting it to the database + since while inserting this thread might block and so would diff --git a/glibc-upstream-2.39-38.patch b/glibc-upstream-2.39-38.patch new file mode 100644 index 0000000..5bda08b --- /dev/null +++ b/glibc-upstream-2.39-38.patch @@ -0,0 +1,384 @@ +commit a9a8d3eebb145779a18d90e3966009a1daa63cd8 +Author: Florian Weimer +Date: Thu Apr 25 15:01:07 2024 +0200 + + CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680) + + This avoids potential memory corruption when the underlying NSS + callback function does not use the buffer space to store all strings + (e.g., for constant strings). + + Instead of custom buffer management, two scratch buffers are used. + This increases stack usage somewhat. + + Scratch buffer allocation failure is handled by return -1 + (an invalid timeout value) instead of terminating the process. + This fixes bug 31679. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit c04a21e050d64a1193a6daab872bca2528bda44b) + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index e22ffa5884e36260..e8fe041846b75cb9 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include "../nss/netgroup.h" + #include "nscd.h" +@@ -65,6 +66,16 @@ struct dataset + char strdata[0]; + }; + ++/* Send a notfound response to FD. Always returns -1 to indicate an ++ ephemeral error. */ ++static time_t ++send_notfound (int fd) ++{ ++ if (fd != -1) ++ TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL)); ++ return -1; ++} ++ + /* Sends a notfound message and prepares a notfound dataset to write to the + cache. Returns true if there was enough memory to allocate the dataset and + returns the dataset in DATASETP, total bytes to write in TOTALP and the +@@ -83,8 +94,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, + total = sizeof (notfound); + timeout = time (NULL) + db->negtimeout; + +- if (fd != -1) +- TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); ++ send_notfound (fd); + + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); + /* If we cannot permanently store the result, so be it. */ +@@ -109,11 +119,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, + return cacheable; + } + ++struct addgetnetgrentX_scratch ++{ ++ /* This is the result that the caller should use. It can be NULL, ++ point into buffer, or it can be in the cache. */ ++ struct dataset *dataset; ++ ++ struct scratch_buffer buffer; ++ ++ /* Used internally in addgetnetgrentX as a staging area. */ ++ struct scratch_buffer tmp; ++ ++ /* Number of bytes in buffer that are actually used. */ ++ size_t buffer_used; ++}; ++ ++static void ++addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch) ++{ ++ scratch->dataset = NULL; ++ scratch_buffer_init (&scratch->buffer); ++ scratch_buffer_init (&scratch->tmp); ++ ++ /* Reserve space for the header. */ ++ scratch->buffer_used = sizeof (struct dataset); ++ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space), ++ "initial buffer space"); ++ memset (scratch->tmp.data, 0, sizeof (struct dataset)); ++} ++ ++static void ++addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch) ++{ ++ scratch_buffer_free (&scratch->buffer); ++ scratch_buffer_free (&scratch->tmp); ++} ++ ++/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH ++ could not be resized, otherwise a pointer to the copy. */ ++static char * ++addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch, ++ const char *s, size_t length) ++{ ++ while (true) ++ { ++ size_t remaining = scratch->buffer.length - scratch->buffer_used; ++ if (remaining >= length) ++ break; ++ if (!scratch_buffer_grow_preserve (&scratch->buffer)) ++ return NULL; ++ } ++ char *copy = scratch->buffer.data + scratch->buffer_used; ++ memcpy (copy, s, length); ++ scratch->buffer_used += length; ++ return copy; ++} ++ ++/* Copy S into SCRATCH, including its null terminator. Returns false ++ if SCRATCH could not be resized. */ ++static bool ++addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s) ++{ ++ if (s == NULL) ++ s = ""; ++ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL; ++} ++ ++/* Caller must initialize and free *SCRATCH. If the return value is ++ negative, this function has sent a notfound response. */ + static time_t + addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *key, uid_t uid, struct hashentry *he, +- struct datahead *dh, struct dataset **resultp, +- void **tofreep) ++ struct datahead *dh, struct addgetnetgrentX_scratch *scratch) + { + if (__glibc_unlikely (debug_level > 0)) + { +@@ -132,14 +209,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + + char *key_copy = NULL; + struct __netgrent data; +- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len); +- size_t buffilled = sizeof (*dataset); +- char *buffer = NULL; + size_t nentries = 0; + size_t group_len = strlen (key) + 1; + struct name_list *first_needed + = alloca (sizeof (struct name_list) + group_len); +- *tofreep = NULL; + + if (netgroup_database == NULL + && !__nss_database_get (nss_database_netgroup, &netgroup_database)) +@@ -151,8 +224,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + memset (&data, '\0', sizeof (data)); +- buffer = xmalloc (buflen); +- *tofreep = buffer; + first_needed->next = first_needed; + memcpy (first_needed->name, key, group_len); + data.needed_groups = first_needed; +@@ -195,8 +266,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + while (1) + { + int e; +- status = getfct.f (&data, buffer + buffilled, +- buflen - buffilled - req->key_len, &e); ++ status = getfct.f (&data, scratch->tmp.data, ++ scratch->tmp.length, &e); + if (status == NSS_STATUS_SUCCESS) + { + if (data.type == triple_val) +@@ -204,68 +275,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *nhost = data.val.triple.host; + const char *nuser = data.val.triple.user; + const char *ndomain = data.val.triple.domain; +- +- size_t hostlen = strlen (nhost ?: "") + 1; +- size_t userlen = strlen (nuser ?: "") + 1; +- size_t domainlen = strlen (ndomain ?: "") + 1; +- +- if (nhost == NULL || nuser == NULL || ndomain == NULL +- || nhost > nuser || nuser > ndomain) +- { +- const char *last = nhost; +- if (last == NULL +- || (nuser != NULL && nuser > last)) +- last = nuser; +- if (last == NULL +- || (ndomain != NULL && ndomain > last)) +- last = ndomain; +- +- size_t bufused +- = (last == NULL +- ? buffilled +- : last + strlen (last) + 1 - buffer); +- +- /* We have to make temporary copies. */ +- size_t needed = hostlen + userlen + domainlen; +- +- if (buflen - req->key_len - bufused < needed) +- { +- buflen += MAX (buflen, 2 * needed); +- /* Save offset in the old buffer. We don't +- bother with the NULL check here since +- we'll do that later anyway. */ +- size_t nhostdiff = nhost - buffer; +- size_t nuserdiff = nuser - buffer; +- size_t ndomaindiff = ndomain - buffer; +- +- char *newbuf = xrealloc (buffer, buflen); +- /* Fix up the triplet pointers into the new +- buffer. */ +- nhost = (nhost ? newbuf + nhostdiff +- : NULL); +- nuser = (nuser ? newbuf + nuserdiff +- : NULL); +- ndomain = (ndomain ? newbuf + ndomaindiff +- : NULL); +- *tofreep = buffer = newbuf; +- } +- +- nhost = memcpy (buffer + bufused, +- nhost ?: "", hostlen); +- nuser = memcpy ((char *) nhost + hostlen, +- nuser ?: "", userlen); +- ndomain = memcpy ((char *) nuser + userlen, +- ndomain ?: "", domainlen); +- } +- +- char *wp = buffer + buffilled; +- wp = memmove (wp, nhost ?: "", hostlen); +- wp += hostlen; +- wp = memmove (wp, nuser ?: "", userlen); +- wp += userlen; +- wp = memmove (wp, ndomain ?: "", domainlen); +- wp += domainlen; +- buffilled = wp - buffer; ++ if (!(addgetnetgrentX_append (scratch, nhost) ++ && addgetnetgrentX_append (scratch, nuser) ++ && addgetnetgrentX_append (scratch, ndomain))) ++ return send_notfound (fd); + ++nentries; + } + else +@@ -317,8 +330,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { +- buflen *= 2; +- *tofreep = buffer = xrealloc (buffer, buflen); ++ if (!scratch_buffer_grow (&scratch->tmp)) ++ return send_notfound (fd); + } + else if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND +@@ -351,10 +364,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + goto maybe_cache_add; + } + +- total = buffilled; ++ /* Capture the result size without the key appended. */ ++ total = scratch->buffer_used; ++ ++ /* Make a copy of the key. The scratch buffer must not move after ++ this point. */ ++ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len); ++ if (key_copy == NULL) ++ return send_notfound (fd); + + /* Fill in the dataset. */ +- dataset = (struct dataset *) buffer; ++ dataset = scratch->buffer.data; + timeout = datahead_init_pos (&dataset->head, total + req->key_len, + total - offsetof (struct dataset, resp), + he == NULL ? 0 : dh->nreloads + 1, +@@ -363,11 +383,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; + dataset->resp.nresults = nentries; +- dataset->resp.result_len = buffilled - sizeof (*dataset); +- +- assert (buflen - buffilled >= req->key_len); +- key_copy = memcpy (buffer + buffilled, key, req->key_len); +- buffilled += req->key_len; ++ dataset->resp.result_len = total - sizeof (*dataset); + + /* Now we can determine whether on refill we have to create a new + record or not. */ +@@ -398,7 +414,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + if (__glibc_likely (newp != NULL)) + { + /* Adjust pointer into the memory block. */ +- key_copy = (char *) newp + (key_copy - buffer); ++ key_copy = (char *) newp + (key_copy - (char *) dataset); + + dataset = memcpy (newp, dataset, total + req->key_len); + cacheable = true; +@@ -439,7 +455,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + out: +- *resultp = dataset; ++ scratch->dataset = dataset; + + return timeout; + } +@@ -460,6 +476,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + if (user != NULL) + key = strchr (key, '\0') + 1; + const char *domain = *key++ ? key : NULL; ++ struct addgetnetgrentX_scratch scratch; ++ ++ addgetnetgrentX_scratch_init (&scratch); + + if (__glibc_unlikely (debug_level > 0)) + { +@@ -475,12 +494,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + group, group_len, + db, uid); + time_t timeout; +- void *tofree; + if (result != NULL) +- { +- timeout = result->head.timeout; +- tofree = NULL; +- } ++ timeout = result->head.timeout; + else + { + request_header req_get = +@@ -489,7 +504,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + .key_len = group_len + }; + timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, +- &result, &tofree); ++ &scratch); ++ result = scratch.dataset; ++ if (timeout < 0) ++ goto out; + } + + struct indataset +@@ -603,7 +621,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + } + + out: +- free (tofree); ++ addgetnetgrentX_scratch_free (&scratch); + return timeout; + } + +@@ -613,11 +631,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req, + const char *key, uid_t uid, struct hashentry *he, + struct datahead *dh) + { +- struct dataset *ignore; +- void *tofree; +- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, +- &ignore, &tofree); +- free (tofree); ++ struct addgetnetgrentX_scratch scratch; ++ addgetnetgrentX_scratch_init (&scratch); ++ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch); ++ addgetnetgrentX_scratch_free (&scratch); ++ if (timeout < 0) ++ timeout = 0; + return timeout; + } + +@@ -661,5 +680,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he, + .key_len = he->len + }; + +- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh); ++ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner, ++ he, dh); ++ if (timeout < 0) ++ timeout = 0; ++ return timeout; + } diff --git a/glibc-upstream-2.39-39.patch b/glibc-upstream-2.39-39.patch new file mode 100644 index 0000000..4dee6ea --- /dev/null +++ b/glibc-upstream-2.39-39.patch @@ -0,0 +1,49 @@ +commit fd658f026f25cf59e8db243bc3b3e09cd5a20ba0 +Author: H.J. Lu +Date: Thu Apr 25 08:06:52 2024 -0700 + + elf: Also compile dl-misc.os with $(rtld-early-cflags) + + Also compile dl-misc.os with $(rtld-early-cflags) to avoid + + Program received signal SIGILL, Illegal instruction. + 0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2", + endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156 + 156 bool positive = true; + (gdb) bt + #0 0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2", + endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156 + #1 0x00007ffff7fdb1a9 in tunable_initialize ( + cur=cur@entry=0x7ffff7ffbc00 , + strval=strval@entry=0x7fffffffe2c9 "2", len=len@entry=1) + at dl-tunables.c:131 + #2 0x00007ffff7fdb3a2 in parse_tunables (valstring=) + at dl-tunables.c:258 + #3 0x00007ffff7fdb5d9 in __GI___tunables_init (envp=0x7fffffffdd58) + at dl-tunables.c:288 + #4 0x00007ffff7fe44c3 in _dl_sysdep_start ( + start_argptr=start_argptr@entry=0x7fffffffdcb0, + dl_main=dl_main@entry=0x7ffff7fe5f80 ) + at ../sysdeps/unix/sysv/linux/dl-sysdep.c:110 + #5 0x00007ffff7fe5cae in _dl_start_final (arg=0x7fffffffdcb0) at rtld.c:494 + #6 _dl_start (arg=0x7fffffffdcb0) at rtld.c:581 + #7 0x00007ffff7fe4b38 in _start () + (gdb) + + when setting GLIBC_TUNABLES in glibc compiled with APX. + Reviewed-by: Florian Weimer + + (cherry picked from commit 049b7684c912dd32b67b1b15b0f43bf07d5f512e) + +diff --git a/elf/Makefile b/elf/Makefile +index 69aa423c4b90127d..a50a988e7362cf3b 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -170,6 +170,7 @@ CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os)) + CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines)) + + # Add the requested compiler flags to the early startup code. ++CFLAGS-dl-misc.os += $(rtld-early-cflags) + CFLAGS-dl-printf.os += $(rtld-early-cflags) + CFLAGS-dl-setup_hash.os += $(rtld-early-cflags) + CFLAGS-dl-sysdep.os += $(rtld-early-cflags) diff --git a/glibc.spec b/glibc.spec index 9687912..b784655 100644 --- a/glibc.spec +++ b/glibc.spec @@ -171,7 +171,7 @@ Version: %{glibcversion} # - It allows using the Release number without the %%dist tag in the dependency # generator to make the generated requires interchangeable between Rawhide # and ELN (.elnYY < .fcXX). -%global baserelease 8 +%global baserelease 9 Release: %{baserelease}%{?dist} # Licenses: @@ -312,6 +312,14 @@ Patch51: glibc-upstream-2.39-28.patch Patch52: glibc-upstream-2.39-29.patch Patch53: glibc-upstream-2.39-30.patch Patch54: glibc-upstream-2.39-31.patch +Patch55: glibc-upstream-2.39-32.patch +Patch56: glibc-upstream-2.39-33.patch +Patch57: glibc-upstream-2.39-34.patch +Patch58: glibc-upstream-2.39-35.patch +Patch59: glibc-upstream-2.39-36.patch +Patch60: glibc-upstream-2.39-37.patch +Patch61: glibc-upstream-2.39-38.patch +Patch62: glibc-upstream-2.39-39.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2488,6 +2496,19 @@ update_gconv_modules_cache () %endif %changelog +* Fri Apr 26 2024 Florian Weimer - 2.39-9 +- nscd is currently not build, so the security fixes below are not relevant. +- Sync with upstream branch release/2.39/master, + commit fd658f026f25cf59e8db243bc3b3e09cd5a20ba0: +- elf: Also compile dl-misc.os with $(rtld-early-cflags) +- CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680) +- CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678) +- CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678) +- CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677) +- x86: Define MINIMUM_X86_ISA_LEVEL in config.h [BZ #31676] +- i386: ulp update for SSE2 --disable-multi-arch configurations +- nptl: Fix tst-cancel30 on kernels without ppoll_time64 support + * Thu Apr 18 2024 Florian Weimer - 2.39-8 - Sync with upstream branch release/2.39/master, commit 31da30f23cddd36db29d5b6a1c7619361b271fb4: