[PATCH v2] libio: Fix CVE-2026-18374 - fopen heap buffer overflow with empty ccs=
=?ks_c_5601-1987?B?vNW1v7HVL1Byb2Nlc3MgJiBJbmZyYSBMYWIoU1IpL7vvvLrA/MDa?= <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Message-ID | <[email protected]> |
Hi all,
My v1 of this patch did not apply cleanly -- most likely my mail client
damaged the inline diff (line wrapping / whitespace), so the automated
apply check failed. I'm resending a clean version generated with
git format-patch on current master and attached to this mail to avoid any
whitespace issues. Apologies for the noise.
The patch has been regenerated on top of current master
(655656fcc6 "manual: Fix some typos in the Low-Level Input/Output
chapter") and verified to apply cleanly with both "git apply --check" and
"git am".
Changes since v1:
- No functional changes. v2 is the same fix as v1, regenerated on
current master as a clean, applyable patch.
Summary
-------
CVE-2026-18374: heap buffer overflow in fopen() with an empty ,ccs=
parameter (GLIBC-SA-2026-0015, CVSS 4.9,
AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L).
When fopen("file", "r,ccs=") is called with an empty charset
specification, endp - (cs + 5) == 0, so only 3 bytes are allocated for
the ccs buffer. This patch rejects an empty ccs= string with EINVAL
before allocation, and extracts the length into a size_t (ccs_len) for
clarity. A regression test is added to libio/tst-fopenloc.c.
The patch is attached as:
0001-CVE-2026-18374-v2.patch
Thanks,
Dongkyun Son
0001-CVE-2026-18374-v2.patch
(application/octet-stream, 2.9 KB)
From 915f9c838d923e75562f96baff6aff45312acd92 Mon Sep 17 00:00:00 2001 From: Dongkyun Son <[email protected]> Date: Fri, 28 Aug 2026 16:03:53 +0900 Subject: [PATCH v2] libio: Fix CVE-2026-18374 - fopen heap buffer overflow with empty ccs= Passing an empty string to the ,ccs= parameter in fopen() could cause a heap buffer overflow. The vulnerable code allocated a buffer of size 3 bytes when endp - (cs + 5) = 0 (empty ccs value), which could be insufficient for the conversion processing. This patch adds validation to reject empty ccs= strings with EINVAL, preventing the buffer overflow. Additionally, the ccs_len variable is extracted to improve code clarity and safety. CVE-2026-18374 - CVSS 4.9 (AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L) Reported-by: AISLE in partnership with Red Hat Signed-off-by: Dongkyun Son <[email protected]> --- libio/fileops.c | 14 ++++++++++++-- libio/tst-fopenloc.c | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/libio/fileops.c b/libio/fileops.c index 9348d7c3a1..2137d0ee1f 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -342,7 +342,17 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode, struct gconv_fcts fcts; struct _IO_codecvt *cc; char *endp = __strchrnul (cs + 5, ','); - char *ccs = malloc (endp - (cs + 5) + 3); + size_t ccs_len = endp - (cs + 5); + + /* Reject empty ccs= string to prevent heap buffer overflow. */ + if (ccs_len == 0) + { + (void) _IO_file_close_it (fp); + __set_errno (EINVAL); + return NULL; + } + + char *ccs = malloc (ccs_len + 3); if (ccs == NULL) { @@ -352,7 +362,7 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode, return NULL; } - *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0'; + *((char *) __mempcpy (ccs, cs + 5, ccs_len)) = '\0'; strip (ccs, ccs); if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0' diff --git a/libio/tst-fopenloc.c b/libio/tst-fopenloc.c index ea3f7b5265..2d2889ae08 100644 --- a/libio/tst-fopenloc.c +++ b/libio/tst-fopenloc.c @@ -85,6 +85,31 @@ do_bz18906 (void) return EXIT_SUCCESS; } +static int +do_cve_2026_18374 (void) +{ + /* CVE-2026-18374 -- reject empty ccs= to prevent heap buffer overflow. */ + + const char *ccs = "r,ccs="; + FILE *fp = fopen (inputfile, ccs); + + if (fp != NULL) + { + printf ("fopen with empty ccs= should have failed but succeeded\n"); + fclose (fp); + return 1; + } + + /* Check that errno is set to EINVAL for invalid ccs parameter. */ + if (errno != EINVAL) + { + printf ("expected EINVAL, got %d\n", errno); + return 1; + } + + return 0; +} + static int do_test (void) { @@ -110,6 +135,7 @@ do_test (void) TEST_COMPARE (do_bz17916 (), 0); TEST_COMPARE (do_bz18906 (), 0); + TEST_COMPARE (do_cve_2026_18374 (), 0); return EXIT_SUCCESS; } -- 2.43.0