From d19eb7001321115280e6f8f448ed4fa74ab1b134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20B=C3=A9rat?= Date: Mon, 11 Aug 2025 14:20:42 +0200 Subject: [PATCH] Fix memory leak after fdopen seek failure - Backport: Remove memory leak in fdopen (bug 31840) - Backport: libio: Test for fdopen memory leak without SEEK_END support (bug 31840) Resolves: RHEL-108475 --- glibc-RHEL-108475-1.patch | 28 +++++++++ glibc-RHEL-108475-2.patch | 120 ++++++++++++++++++++++++++++++++++++++ glibc.spec | 7 ++- 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 glibc-RHEL-108475-1.patch create mode 100644 glibc-RHEL-108475-2.patch diff --git a/glibc-RHEL-108475-1.patch b/glibc-RHEL-108475-1.patch new file mode 100644 index 0000000..30eb2de --- /dev/null +++ b/glibc-RHEL-108475-1.patch @@ -0,0 +1,28 @@ +commit b2c3ee3724900975deaf5eae57640bb0c2d7315e +Author: Andreas Schwab +Date: Tue Jun 4 11:01:11 2024 +0200 + + Remove memory leak in fdopen (bug 31840) + + Deallocate the memory for the FILE structure when seeking to the end fails + in append mode. + + Fixes: ea33158c96 ("Fix offset caching for streams and use it for ftell (BZ #16680)") + +diff --git a/libio/iofdopen.c b/libio/iofdopen.c +index 2583fb825573aae4..14fbc7b257ad7724 100644 +--- a/libio/iofdopen.c ++++ b/libio/iofdopen.c +@@ -156,7 +156,11 @@ _IO_new_fdopen (int fd, const char *mode) + { + off64_t new_pos = _IO_SYSSEEK (&new_f->fp.file, 0, _IO_seek_end); + if (new_pos == _IO_pos_BAD && errno != ESPIPE) +- return NULL; ++ { ++ _IO_un_link (&new_f->fp); ++ free (new_f); ++ return NULL; ++ } + } + return &new_f->fp.file; + } diff --git a/glibc-RHEL-108475-2.patch b/glibc-RHEL-108475-2.patch new file mode 100644 index 0000000..a6aa741 --- /dev/null +++ b/glibc-RHEL-108475-2.patch @@ -0,0 +1,120 @@ +commit d0106b6ae26c8cc046269358a77188105c99d5e3 +Author: Florian Weimer +Date: Tue Jun 4 14:37:35 2024 +0200 + + libio: Test for fdopen memory leak without SEEK_END support (bug 31840) + + The bug report used /dev/mem, but /proc/self/mem works as well + (if available). + +diff --git a/libio/Makefile b/libio/Makefile +index 92d6c6bcab1818d0..b189455bb9b8fd1b 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -94,6 +94,7 @@ tests = \ + tst-eof \ + tst-ext \ + tst-ext2 \ ++ tst-fdopen-seek-failure \ + tst-fgetc-after-eof \ + tst-fgetwc \ + tst-fgetws \ +@@ -253,6 +254,9 @@ tst_wprintf2-ARGS = "Some Text" + + test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace \ + LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so ++tst-fdopen-seek-failure-ENV = \ ++ MALLOC_TRACE=$(objpfx)tst-fdopen-seek-failure.mtrace \ ++ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so + tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace \ + LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so + tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace \ +@@ -261,6 +265,7 @@ tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace \ + LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so + + generated += test-fmemopen.mtrace test-fmemopen.check ++generated += tst-fdopen-seek-failure.mtrace tst-fdopen-seek-failure.check + generated += tst-fopenloc.mtrace tst-fopenloc.check + generated += tst-bz22415.mtrace tst-bz22415.check + +@@ -283,8 +288,12 @@ shared-only-routines = oldiofopen oldiofdopen oldiofclose oldfileops \ + oldiofsetpos64 + + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \ +- $(objpfx)tst-bz22415-mem.out ++tests-special += \ ++ $(objpfx)test-fmemopen-mem.out \ ++ $(objpfx)test-freopen.out \ ++ $(objpfx)tst-bz22415-mem.out \ ++ $(objpfx)tst-fdopen-seek-failure-mem.out \ ++ # tests-special + ifeq (yes,$(build-shared)) + # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared + # library is enabled since they depend on tst-fopenloc.out. +@@ -372,6 +381,11 @@ $(objpfx)test-fmemopen-mem.out: $(objpfx)test-fmemopen.out + $(common-objpfx)malloc/mtrace $(objpfx)test-fmemopen.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 > $@; \ ++ $(evaluate-test) ++ + $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-fopenloc.mtrace > $@; \ + $(evaluate-test) +diff --git a/libio/tst-fdopen-seek-failure.c b/libio/tst-fdopen-seek-failure.c +new file mode 100644 +index 0000000000000000..5c4d40ab34158571 +--- /dev/null ++++ b/libio/tst-fdopen-seek-failure.c +@@ -0,0 +1,48 @@ ++/* Test for fdopen memory leak without SEEK_END support (bug 31840). ++ 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 ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ ++ /* This file is special because it is seekable, but only ++ with SEEK_SET, not SEEK_END. */ ++ int fd = open ("/proc/self/mem", O_RDWR); ++ if (fd < 0) ++ FAIL_UNSUPPORTED ("/proc/self/mem not found: %m"); ++ FILE *fp = fdopen (fd, "a"); ++ /* The fdopen call should have failed because it tried to use ++ SEEK_END. */ ++ TEST_VERIFY (fp == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ xclose (fd); ++ return 0; ++} ++ ++#include diff --git a/glibc.spec b/glibc.spec index 895d978..99be6e2 100644 --- a/glibc.spec +++ b/glibc.spec @@ -147,7 +147,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 53 +%global baserelease 54 Release: %{baserelease}%{?dist} # Licenses: @@ -649,6 +649,8 @@ Patch323: glibc-RHEL-107695-16.patch Patch324: glibc-RHEL-107695-17.patch Patch325: glibc-RHEL-107695-18.patch Patch326: glibc-RHEL-107695-19.patch +Patch327: glibc-RHEL-108475-1.patch +Patch328: glibc-RHEL-108475-2.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2662,6 +2664,9 @@ update_gconv_modules_cache () %endif %changelog +* Mon Aug 11 2025 Frédéric Bérat - 2.39-54 +- Fix memory leak after fdopen seek failure (RHEL-108475) + * Wed Aug 06 2025 Frédéric Bérat - 2.39-53 - Updated glibc to support Linux 6.15 kernel system calls and constants. (RHEL-107695)