From: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
To: Aurelien Jarno <aurelien@aurel32.net>, libc-stable@sourceware.org
Cc: Carlos O'Donell <carlos@redhat.com>
Subject: Re: [COMMITTED 2.31] iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
Date: Mon, 22 Apr 2024 10:13:57 -0300 [thread overview]
Message-ID: <a62dbd95-6e5f-492d-97b9-9f9ef8c4e0ac@linaro.org> (raw)
In-Reply-To: <20240419195247.1794363-1-aurelien@aurel32.net>
I think we also need to update the advisories/GLIBC-SA-2024-0004 with this
backport.
On 19/04/24 16:52, Aurelien Jarno wrote:
> From: Charles Fol <folcharles@gmail.com>
>
> ISO-2022-CN-EXT uses escape sequences to indicate character set changes
> (as specified by RFC 1922). While the SOdesignation has the expected
> bounds checks, neither SS2designation nor SS3designation have its;
> allowing a write overflow of 1, 2, or 3 bytes with fixed values:
> '$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
>
> Checked on aarch64-linux-gnu.
>
> Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> Tested-by: Carlos O'Donell <carlos@redhat.com>
>
> (cherry picked from commit f9dc609e06b1136bb0408be9605ce7973a767ada)
> ---
> iconvdata/Makefile | 5 +-
> iconvdata/iso-2022-cn-ext.c | 12 +++
> iconvdata/tst-iconv-iso-2022-cn-ext.c | 128 ++++++++++++++++++++++++++
> 3 files changed, 144 insertions(+), 1 deletion(-)
> create mode 100644 iconvdata/tst-iconv-iso-2022-cn-ext.c
>
> diff --git a/iconvdata/Makefile b/iconvdata/Makefile
> index 8fbb67a52b..31b1cf8a9f 100644
> --- a/iconvdata/Makefile
> +++ b/iconvdata/Makefile
> @@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
> tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
> tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
> bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \
> - bug-iconv15
> + bug-iconv15 \
> + tst-iconv-iso-2022-cn-ext
> ifeq ($(have-thread-library),yes)
> tests += bug-iconv3
> endif
> @@ -322,6 +323,8 @@ $(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
> $(addprefix $(objpfx),$(modules.so))
> $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
> $(addprefix $(objpfx),$(modules.so))
> +$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
> + $(addprefix $(objpfx),$(modules.so))
>
> $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
> $(addprefix $(objpfx),$(modules.so)) \
> diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
> index 947b807421..34e1010bed 100644
> --- a/iconvdata/iso-2022-cn-ext.c
> +++ b/iconvdata/iso-2022-cn-ext.c
> @@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
> { \
> const char *escseq; \
> \
> + if (outptr + 4 > outend) \
> + { \
> + result = __GCONV_FULL_OUTPUT; \
> + break; \
> + } \
> + \
> assert (used == CNS11643_2_set); /* XXX */ \
> escseq = "*H"; \
> *outptr++ = ESC; \
> @@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
> { \
> const char *escseq; \
> \
> + if (outptr + 4 > outend) \
> + { \
> + result = __GCONV_FULL_OUTPUT; \
> + break; \
> + } \
> + \
> assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
> escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
> *outptr++ = ESC; \
> diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
> new file mode 100644
> index 0000000000..96a8765fd5
> --- /dev/null
> +++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
> @@ -0,0 +1,128 @@
> +/* Verify ISO-2022-CN-EXT does not write out of the bounds.
> + 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include <errno.h>
> +#include <iconv.h>
> +#include <sys/mman.h>
> +
> +#include <support/xunistd.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +
> +/* The test sets up a two memory page buffer with the second page marked
> + PROT_NONE to trigger a fault if the conversion writes beyond the exact
> + expected amount. Then we carry out various conversions and precisely
> + place the start of the output buffer in order to trigger a SIGSEGV if the
> + process writes anywhere between 1 and page sized bytes more (only one
> + PROT_NONE page is setup as a canary) than expected. These tests exercise
> + all three of the cases in ISO-2022-CN-EXT where the converter must switch
> + character sets and may run out of buffer space while doing the
> + operation. */
> +
> +static int
> +do_test (void)
> +{
> + iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
> + TEST_VERIFY_EXIT (cd != (iconv_t) -1);
> +
> + char *ntf;
> + size_t ntfsize;
> + char *outbufbase;
> + {
> + int pgz = getpagesize ();
> + TEST_VERIFY_EXIT (pgz > 0);
> + ntfsize = 2 * pgz;
> +
> + ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
> + | MAP_ANONYMOUS, -1);
> + xmprotect (ntf + pgz, pgz, PROT_NONE);
> +
> + outbufbase = ntf + pgz;
> + }
> +
> + /* Check if SOdesignation escape sequence does not trigger an OOB write. */
> + {
> + char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
> +
> + for (int i = 0; i < 9; i++)
> + {
> + char *inp = inbuf;
> + size_t inleft = sizeof (inbuf) - 1;
> +
> + char *outp = outbufbase - i;
> + size_t outleft = i;
> +
> + TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
> + == (size_t) -1);
> + TEST_COMPARE (errno, E2BIG);
> +
> + TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
> + }
> + }
> +
> + /* Same as before for SS2designation. */
> + {
> + char inbuf[] = "㴽 \xe3\xb4\xbd";
> +
> + for (int i = 0; i < 14; i++)
> + {
> + char *inp = inbuf;
> + size_t inleft = sizeof (inbuf) - 1;
> +
> + char *outp = outbufbase - i;
> + size_t outleft = i;
> +
> + TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
> + == (size_t) -1);
> + TEST_COMPARE (errno, E2BIG);
> +
> + TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
> + }
> + }
> +
> + /* Same as before for SS3designation. */
> + {
> + char inbuf[] = "劄 \xe5\x8a\x84";
> +
> + for (int i = 0; i < 14; i++)
> + {
> + char *inp = inbuf;
> + size_t inleft = sizeof (inbuf) - 1;
> +
> + char *outp = outbufbase - i;
> + size_t outleft = i;
> +
> + TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
> + == (size_t) -1);
> + TEST_COMPARE (errno, E2BIG);
> +
> + TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
> + }
> + }
> +
> + TEST_VERIFY_EXIT (iconv_close (cd) != -1);
> +
> + xmunmap (ntf, ntfsize);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
prev parent reply other threads:[~2024-04-22 13:14 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-19 19:52 Aurelien Jarno
2024-04-22 13:13 ` Adhemerval Zanella Netto [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a62dbd95-6e5f-492d-97b9-9f9ef8c4e0ac@linaro.org \
--to=adhemerval.zanella@linaro.org \
--cc=aurelien@aurel32.net \
--cc=carlos@redhat.com \
--cc=libc-stable@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).