diff --git a/glibc-RHEL-115820-1.patch b/glibc-RHEL-115820-1.patch new file mode 100644 index 0000000..6ffdbe5 --- /dev/null +++ b/glibc-RHEL-115820-1.patch @@ -0,0 +1,79 @@ +commit 3e4a01870ef9605ccf6475215a4b32aa86d5d206 +Author: Aaron Merey +Date: Thu Aug 29 12:02:25 2024 -0400 + + Test fclose on an unopened file. + + Add new file libio/tst-fclosed-unopened.c that tests whether fclose on + an unopened file returns EOF. + + Calling fclose on unopened files normally causes a use-after-free bug, + however the standard streams are an exception since they are not + deallocated by fclose. + + fclose returning EOF for unopened files is not part of the external + contract but there are dependancies on this behaviour. For example, + gnulib's close_stdout in lib/closeout.c. + + Tested for x86_64. + + Signed-off-by: Aaron Merey + +diff --git a/libio/Makefile b/libio/Makefile +index 6cf5b3464b5bb4bf..3252c8c52fc3c773 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -95,6 +95,7 @@ tests = \ + tst-eof \ + tst-ext \ + tst-ext2 \ ++ tst-fclose-unopened \ + tst-fdopen-seek-failure \ + tst-fgetc-after-eof \ + tst-fgetwc \ +diff --git a/libio/tst-fclose-unopened.c b/libio/tst-fclose-unopened.c +new file mode 100644 +index 0000000000000000..1f1cad042d8d72bf +--- /dev/null ++++ b/libio/tst-fclose-unopened.c +@@ -0,0 +1,40 @@ ++/* Test using fclose on an unopened file. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++/* Verify that fclose on an unopened file returns EOF. This is not part ++ of the fclose external contract but there are dependancies on this ++ behaviour. */ ++ ++static int ++do_test (void) ++{ ++ TEST_COMPARE (fclose (stdin), 0); ++ ++ /* Attempt to close the unopened file and verify that EOF is returned. ++ Calling fclose on a file twice normally causes a use-after-free bug, ++ however the standard streams are an exception since they are not ++ deallocated by fclose. */ ++ TEST_COMPARE (fclose (stdin), EOF); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-RHEL-115820-2.patch b/glibc-RHEL-115820-2.patch new file mode 100644 index 0000000..74afe9c --- /dev/null +++ b/glibc-RHEL-115820-2.patch @@ -0,0 +1,155 @@ +commit 35dc62de3d5d73a91d4ca8fa9799b510a34d170d +Author: Aaron Merey +Date: Thu Sep 19 09:53:23 2024 -0400 + + Add another test for fclose on an unopened file + + Add new file libio/tst-fclose-unopened2.c that tests whether fclose on an + unopened file returns EOF. + + This test differs from tst-fclose-unopened.c by ensuring the file's buffer + is allocated prior to double-fclose. A comment in tst-fclose-unopened.c + now clarifies that it is testing a file with an unallocated buffer. + + Calling fclose on unopened files normally causes a use-after-free bug, + however the standard streams are an exception since they are not + deallocated by fclose. + + Tested for x86_64. + + Reviewed-by: Carlos O'Donell + +diff --git a/libio/Makefile b/libio/Makefile +index 3252c8c52fc3c773..efa60525b39331da 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -96,6 +96,7 @@ tests = \ + tst-ext \ + tst-ext2 \ + tst-fclose-unopened \ ++ tst-fclose-unopened2 \ + tst-fdopen-seek-failure \ + tst-fgetc-after-eof \ + tst-fgetwc \ +@@ -254,6 +255,9 @@ LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map + + tst_wprintf2-ARGS = "Some Text" + ++tst-fclose-unopened2-ENV = \ ++ MALLOC_TRACE=$(objpfx)tst-fclose-unopened2.mtrace \ ++ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so + test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace \ + LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so + tst-fdopen-seek-failure-ENV = \ +@@ -278,6 +282,8 @@ generated += \ + tst-bz22415.mtrace \ + tst-bz24228.check \ + tst-bz24228.mtrace \ ++ tst-fclose-unopened2.check \ ++ tst-fclose-unopened2.mtrace \ + tst-fdopen-seek-failure.check \ + tst-fdopen-seek-failure.mtrace \ + tst-fopenloc.check \ +@@ -316,6 +322,7 @@ tests-special += \ + $(objpfx)test-fmemopen-mem.out \ + $(objpfx)tst-bz22415-mem.out \ + $(objpfx)tst-bz24228-mem.out \ ++ $(objpfx)tst-fclose-unopened2-mem.out \ + $(objpfx)tst-fdopen-seek-failure-mem.out \ + $(objpfx)tst-fopenloc-mem.out \ + # tests-special +@@ -403,6 +410,11 @@ $(objpfx)test-fmemopen-mem.out: $(objpfx)test-fmemopen.out + $(common-objpfx)malloc/mtrace $(objpfx)test-fmemopen.mtrace > $@; \ + $(evaluate-test) + ++$(objpfx)tst-fclose-unopened2-mem.out: $(objpfx)tst-fclose-unopened2.out ++ $(common-objpfx)malloc/mtrace \ ++ $(objpfx)tst-fclose-unopened2.mtrace > $@; \ ++ $(evaluate-test) ++ + $(objpfx)tst-fdopen-seek-failure-mem.out: $(objpfx)tst-fdopen-seek-failure.out + $(common-objpfx)malloc/mtrace \ + $(objpfx)tst-fdopen-seek-failure.mtrace > $@; \ +diff --git a/libio/tst-fclose-unopened.c b/libio/tst-fclose-unopened.c +index 1f1cad042d8d72bf..4fed2ffdfe8cf9b4 100644 +--- a/libio/tst-fclose-unopened.c ++++ b/libio/tst-fclose-unopened.c +@@ -19,9 +19,11 @@ + #include + #include + +-/* Verify that fclose on an unopened file returns EOF. This is not part +- of the fclose external contract but there are dependancies on this +- behaviour. */ ++/* Verify that fclose on an unopened file returns EOF. This test uses ++ a file with an unallocated buffer. ++ ++ This is not part of the fclose external contract but there are ++ dependencies on this behaviour. */ + + static int + do_test (void) +diff --git a/libio/tst-fclose-unopened2.c b/libio/tst-fclose-unopened2.c +new file mode 100644 +index 0000000000000000..1e99d9dc3d561b80 +--- /dev/null ++++ b/libio/tst-fclose-unopened2.c +@@ -0,0 +1,51 @@ ++/* Test using fclose on an unopened file. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++/* Verify that fclose on an unopened file returns EOF. This test uses ++ a file with an allocated buffer. ++ ++ This is not part of the fclose external contract but there are ++ dependencies on this behaviour. */ ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ ++ /* Input file tst-fclose-unopened2.input has 6 bytes plus newline. */ ++ char buf[6]; ++ ++ /* Read from the file to ensure its internal buffer is allocated. */ ++ TEST_COMPARE (fread (buf, 1, sizeof (buf), stdin), sizeof (buf)); ++ ++ TEST_COMPARE (fclose (stdin), 0); ++ ++ /* Attempt to close the unopened file and verify that EOF is returned. ++ Calling fclose on a file twice normally causes a use-after-free bug, ++ however the standard streams are an exception since they are not ++ deallocated by fclose. */ ++ TEST_COMPARE (fclose (stdin), EOF); ++ ++ return 0; ++} ++ ++#include +diff --git a/libio/tst-fclose-unopened2.input b/libio/tst-fclose-unopened2.input +new file mode 100644 +index 0000000000000000..399f9ba41aff870b +--- /dev/null ++++ b/libio/tst-fclose-unopened2.input +@@ -0,0 +1 @@ ++fclose diff --git a/glibc-RHEL-119657-1.patch b/glibc-RHEL-119657-1.patch new file mode 100644 index 0000000..35838c8 --- /dev/null +++ b/glibc-RHEL-119657-1.patch @@ -0,0 +1,281 @@ +commit 480660e270057e40381fd6d4c47f89116415928e +Author: Florian Weimer +Date: Thu Sep 18 19:11:38 2025 +0200 + + support: Add support_accept_oom to heuristically support OOM errors + + Some tests may trigger the kernel OOM handler under conditions + which are difficult to predict (depending on available RAM and + swap space). If we can determine specific regions which might + do this and this does not contradict the test object, the + functions support_accept_oom (true) and support_accept_oom (false) + can be called at the start and end, and the test driver will + ignore SIGKILL signals. + + Reviewed-by: Carlos O'Donell + +diff --git a/support/Makefile b/support/Makefile +index 6809c234e9314163..af3f69f5df76e6f9 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -322,6 +322,7 @@ tests = \ + tst-support-open-dev-null-range \ + tst-support-openpty \ + tst-support-process_state \ ++ tst-support_accept_oom \ + tst-support_blob_repeat \ + tst-support_capture_subprocess \ + tst-support_descriptors \ +diff --git a/support/check.h b/support/check.h +index 8f41e5b99fc17472..757b83221fddbe40 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -196,9 +196,11 @@ void support_test_compare_string_wide (const wchar_t *left, + const char *left_expr, + const char *right_expr); + +-/* Internal function called by the test driver. */ ++/* Internal functions called by the test driver. */ + int support_report_failure (int status) + __attribute__ ((weak, warn_unused_result)); ++int support_is_oom_accepted (void) ++ __attribute__ ((weak, warn_unused_result)); + + /* Internal function used to test the failure recording framework. */ + void support_record_failure_reset (void); +diff --git a/support/support.h b/support/support.h +index 1a77f7979330d60c..2717e5583add690b 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -239,6 +239,15 @@ int support_open_dev_null_range (int num, int flags, mode_t mode); + /* Check if kernel supports set VMA range name. */ + extern bool support_set_vma_name_supported (void); + ++/* If invoked with a true argument, it instructs the supervising ++ process to ignore unexpected termination of the test process, ++ likely due to an OOM error. (This can theoretically mask other ++ test errors, so it should be used sparingly.) ++ ++ If invoked with a false argument, the default behavior is restored, ++ and OOM-induced errors result in test failure. */ ++void support_accept_oom (bool); ++ + __END_DECLS + + #endif /* SUPPORT_H */ +diff --git a/support/support_record_failure.c b/support/support_record_failure.c +index 72ee2b232fb2b08c..7b0db19ed6bcaa7e 100644 +--- a/support/support_record_failure.c ++++ b/support/support_record_failure.c +@@ -31,6 +31,10 @@ + failure is detected, so that even if the counter wraps around to + zero, the failure of a test can be detected. + ++ If the accept_oom member is not zero, the supervisor process will ++ use heuristics to suppress process termination due to OOM ++ conditions. ++ + The init constructor function below puts *state on a shared + anonymous mapping, so that failure reports from subprocesses + propagate to the parent process. */ +@@ -38,6 +42,7 @@ struct test_failures + { + unsigned int counter; + unsigned int failed; ++ unsigned int accept_oom; + }; + static struct test_failures *state; + +@@ -122,3 +127,34 @@ support_record_failure_barrier (void) + exit (1); + } + } ++ ++void ++support_accept_oom (bool onoff) ++{ ++ if (onoff) ++ { ++ /* One thread detects the overflow. */ ++ if (__atomic_fetch_add (&state->accept_oom, 1, __ATOMIC_RELAXED) ++ == UINT_MAX) ++ { ++ puts ("error: OOM acceptance counter overflow"); ++ exit (1); ++ } ++ } ++ else ++ { ++ /* One thread detects the underflow. */ ++ if (__atomic_fetch_add (&state->accept_oom, -1, __ATOMIC_RELAXED) ++ == 0) ++ { ++ puts ("error: OOM acceptance counter underflow"); ++ exit (1); ++ } ++ } ++} ++ ++int ++support_is_oom_accepted (void) ++{ ++ return __atomic_load_n (&state->accept_oom, __ATOMIC_RELAXED) != 0; ++} +diff --git a/support/support_test_main.c b/support/support_test_main.c +index cca82d8d820f9360..85f885165c528989 100644 +--- a/support/support_test_main.c ++++ b/support/support_test_main.c +@@ -264,6 +264,20 @@ adjust_exit_status (int status) + return status; + } + ++/* Return true if the exit status looks like it may have been ++ triggered by kernel OOM handling, and support_accept_oom (true) was ++ active in the test process. This is a very approximate check. ++ Unfortunately, the SI_KERNEL value for si_code in siginfo_t is not ++ observable via waitid (it gets translated to CLD_KILLED. */ ++static bool ++accept_oom_heuristic (int status) ++{ ++ return (WIFSIGNALED (status) ++ && WTERMSIG (status) == SIGKILL ++ && support_is_oom_accepted != NULL ++ && support_is_oom_accepted ()); ++} ++ + int + support_test_main (int argc, char **argv, const struct test_config *config) + { +@@ -497,6 +511,11 @@ support_test_main (int argc, char **argv, const struct test_config *config) + /* Process was killed by timer or other signal. */ + else + { ++ if (accept_oom_heuristic (status)) ++ { ++ puts ("Heuristically determined OOM termination; SIGKILL ignored"); ++ exit (adjust_exit_status (EXIT_UNSUPPORTED)); ++ } + if (config->expected_signal == 0) + { + printf ("Didn't expect signal from child: got `%s'\n", +diff --git a/support/tst-support_accept_oom.c b/support/tst-support_accept_oom.c +new file mode 100644 +index 0000000000000000..42a4328cbc60764d +--- /dev/null ++++ b/support/tst-support_accept_oom.c +@@ -0,0 +1,115 @@ ++/* Test that OOM error suppression works. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* This test reacts to the reject_oom and inject_error environment ++ variables. It is never executed automatically because it can run ++ for a very long time on large systems, and is generally stressful ++ to the system. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* If true, support_accept_oom is called. */ ++static bool accept_oom; ++ ++/* System page size. Allocations are always at least that large. */ ++static size_t page_size; ++ ++/* All allocated bytes. */ ++static size_t total_bytes; ++ ++/* Try to allocate SIZE bytes of memory, and ensure that is backed by ++ actual memory. */ ++static bool ++populate_memory (size_t size) ++{ ++ TEST_COMPARE (size % page_size, 0); ++ char *ptr = mmap (NULL, size, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ if (ptr == MAP_FAILED) ++ return false; ++ ++ if (accept_oom) ++ support_accept_oom (true); ++ ++ /* Ensure that the kernel allocates backing storage. Make the pages ++ distinct using the total_bytes counter. */ ++ for (size_t offset = 0; offset < size; offset += page_size) ++ { ++ memcpy (ptr + offset, &total_bytes, sizeof (total_bytes)); ++ total_bytes += page_size; ++ } ++ ++ if (accept_oom) ++ support_accept_oom (false); ++ ++ return true; ++} ++ ++static int ++do_test (void) ++{ ++ if (getenv ("oom_test_active") == NULL) ++ { ++ puts ("info: This test does nothing by default."); ++ puts ("info: Set the oom_test_active environment variable to enable it."); ++ puts ("info: Consider testing with inject_error and reject_oom as well."); ++ return 0; ++ } ++ ++ accept_oom = getenv ("reject_oom") == NULL; ++ ++ page_size = sysconf (_SC_PAGESIZE); ++ size_t size = page_size; ++ ++ /* The environment variable can be set to trigger a test failure. ++ The OOM event should not obscure this error. */ ++ TEST_COMPARE_STRING (getenv ("inject_error"), NULL); ++ ++ /* Grow the allocation until allocation fails. */ ++ while (true) ++ { ++ size_t new_size = 2 * size; ++ if (new_size == 0 || !populate_memory (new_size)) ++ break; ++ size = new_size; ++ } ++ ++ while (true) ++ { ++ if (!populate_memory (size)) ++ { ++ /* Decrease size and see if the allocation succeeds. */ ++ size /= 2; ++ if (size < page_size) ++ FAIL_UNSUPPORTED ("could not trigger OOM" ++ " after allocating %zu bytes", ++ total_bytes); ++ } ++ } ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-RHEL-119657-2.patch b/glibc-RHEL-119657-2.patch new file mode 100644 index 0000000..01145d9 --- /dev/null +++ b/glibc-RHEL-119657-2.patch @@ -0,0 +1,30 @@ +commit 855a67c3cc81be4fc806c66e3e01b53e352a4e9f +Author: Florian Weimer +Date: Thu Sep 18 19:11:38 2025 +0200 + + stdlib: Use support_accept_oom in test-bz22786 + + The realpath call may trigger OOM termination of the test process + under difficult-to-predict circumstances. (It depends on available + RAM and swap.) Therefore, instruct the test driver to ignore + an OOM process termination during the realpath call. + + Reviewed-by: Carlos O'Donell + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index 37bd63ec7141c61c..16a8f2edf22deefa 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -60,8 +60,11 @@ do_test (void) + *(p++) = '/'; + p[path_len - (p - path) - 1] = '\0'; + +- /* This call crashes before the fix for bz22786 on 32-bit platforms. */ ++ /* This call crashes before the fix for bz22786 on 32-bit platforms. ++ It may trigger an OOM event. */ ++ support_accept_oom (true); + p = realpath (path, NULL); ++ support_accept_oom (false); + TEST_VERIFY (p == NULL); + /* For 64-bit platforms readlink return ENAMETOOLONG, while for 32-bit + realpath will try to allocate a buffer larger than PTRDIFF_MAX. */ diff --git a/glibc.spec b/glibc.spec index 6e1647a..04b55bc 100644 --- a/glibc.spec +++ b/glibc.spec @@ -2348,7 +2348,7 @@ update_gconv_modules_cache () %endif %changelog -* Tue Oct 07 2025 Eduard Abdullin - 2.39-71.alma.1 +* Wed Oct 08 2025 Eduard Abdullin - 2.39-73.alma.1 - Overwrite target for x86_64_v2 - Update patch-git.lua to handle AlmaLinux branches correctly