diff --git a/backport-CVE-2020-29562-iconv-Fix-incorrect-UCS4-inner-loop-bounds-BZ-26923.patch b/backport-CVE-2020-29562-iconv-Fix-incorrect-UCS4-inner-loop-bounds-BZ-26923.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7996373c566f80232f1dd4a5eac42db0136d934 --- /dev/null +++ b/backport-CVE-2020-29562-iconv-Fix-incorrect-UCS4-inner-loop-bounds-BZ-26923.patch @@ -0,0 +1,155 @@ +From 228edd356f03bf62dcf2b1335f25d43c602ee68d Mon Sep 17 00:00:00 2001 +From: Michael Colavita +Date: Thu, 19 Nov 2020 11:44:40 -0500 +Subject: [PATCH] iconv: Fix incorrect UCS4 inner loop bounds (BZ#26923) + +reason:Fix incorrect UCS4 inner loop bounds +Conflict:NA +Reference:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-29562 + +Previously, in UCS4 conversion routines we limit the number of +characters we examine to the minimum of the number of characters in the +input and the number of characters in the output. This is not the +correct behavior when __GCONV_IGNORE_ERRORS is set, as we do not consume +an output character when we skip a code unit. Instead, track the input +and output pointers and terminate the loop when either reaches its +limit. + +This resolves assertion failures when resetting the input buffer in a step of +iconv, which assumes that the input will be fully consumed given sufficient +output space. +--- + iconv/Makefile | 2 +- + iconv/gconv_simple.c | 16 ++++---------- + iconv/tst-iconv8.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 55 insertions(+), 13 deletions(-) + create mode 100644 iconv/tst-iconv8.c + +diff --git a/iconv/Makefile b/iconv/Makefile +index 73d983af..54fed214 100644 +--- a/iconv/Makefile ++++ b/iconv/Makefile +@@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION + CFLAGS-simple-hash.c += -I../locale + + tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ +- tst-iconv7 ++ tst-iconv7 tst-iconv8 + + others = iconv_prog iconvconfig + others-pie += iconv_prog iconvconfig +diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c +index c487b892..f47d56f4 100644 +--- a/iconv/gconv_simple.c ++++ b/iconv/gconv_simple.c +@@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step, + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; +- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; + int result; +- size_t cnt; + +- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) ++ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) + { + uint32_t inval; + +@@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step, + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; +- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; + int result; +- size_t cnt; + +- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) ++ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) + { + if (__glibc_unlikely (inptr[0] > 0x80)) + { +@@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step, + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; +- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; + int result; +- size_t cnt; + +- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) ++ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) + { + uint32_t inval; + +@@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step, + int flags = step_data->__flags; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; +- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; + int result; +- size_t cnt; + +- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) ++ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) + { + if (__glibc_unlikely (inptr[3] > 0x80)) + { +diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c +new file mode 100644 +index 00000000..0b92b19f +--- /dev/null ++++ b/iconv/tst-iconv8.c +@@ -0,0 +1,50 @@ ++/* Test iconv behavior on UCS4 conversions with //IGNORE. ++ Copyright (C) 2020 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 ++ . */ ++ ++/* Derived from BZ #26923 */ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* ++ * Convert sequence beginning with an irreversible character into buffer that ++ * is too small. ++ */ ++ char input[12] = "\xe1\x80\xa1" "AAAAAAAAA"; ++ char *inptr = input; ++ size_t insize = sizeof (input); ++ char output[6]; ++ char *outptr = output; ++ size_t outsize = sizeof (output); ++ ++ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1); ++ TEST_VERIFY (errno == E2BIG); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include +-- +2.23.0 + diff --git a/backport-Fix-CVE-2020-29573-x86-Harden-printf-against-non-normal-long-double-val.patch b/backport-Fix-CVE-2020-29573-x86-Harden-printf-against-non-normal-long-double-val.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff88c28559420da34d813f566601cab217b00cf3 --- /dev/null +++ b/backport-Fix-CVE-2020-29573-x86-Harden-printf-against-non-normal-long-double-val.patch @@ -0,0 +1,128 @@ +From 681900d29683722b1cb0a8e565a0585846ec5a61 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 22 Sep 2020 19:07:48 +0200 +Subject: [PATCH] x86: Harden printf against non-normal long double values (bug + 26649) + +The behavior of isnan/__builtin_isnan on bit patterns that do not +correspond to something that the CPU would produce from valid inputs +is currently under-defined in the toolchain. (The GCC built-in and +glibc disagree.) + +The isnan check in PRINTF_FP_FETCH in stdio-common/printf_fp.c +assumes the GCC behavior that returns true for non-normal numbers +which are not specified as NaN. (The glibc implementation returns +false for such numbers.) + +At present, passing non-normal numbers to __mpn_extract_long_double +causes this function to produce irregularly shaped multi-precision +integers, triggering undefined behavior in __printf_fp_l. + +With GCC 10 and glibc 2.32, this behavior is not visible because +__builtin_isnan is used, which avoids calling +__mpn_extract_long_double in this case. This commit updates the +implementation of __mpn_extract_long_double so that regularly shaped +multi-precision integers are produced in this case, avoiding +undefined behavior in __printf_fp_l. +--- + sysdeps/x86/Makefile | 4 ++ + sysdeps/x86/ldbl2mpn.c | 8 ++++ + sysdeps/x86/tst-ldbl-nonnormal-printf.c | 52 +++++++++++++++++++++++++ + 3 files changed, 64 insertions(+) + create mode 100644 sysdeps/x86/tst-ldbl-nonnormal-printf.c + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index c369faf00d..081cc72e93 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -11,6 +11,10 @@ tests += tst-get-cpu-features tst-get-cpu-features-static \ + tests-static += tst-get-cpu-features-static + endif + ++ifeq ($(subdir),math) ++tests += tst-ldbl-nonnormal-printf ++endif # $(subdir) == math ++ + ifeq ($(subdir),setjmp) + gen-as-const-headers += jmp_buf-ssp.sym + sysdep_routines += __longjmp_cancel +diff --git a/sysdeps/x86/ldbl2mpn.c b/sysdeps/x86/ldbl2mpn.c +index ec8464eef7..23afedfb67 100644 +--- a/sysdeps/x86/ldbl2mpn.c ++++ b/sysdeps/x86/ldbl2mpn.c +@@ -115,6 +115,14 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, + && res_ptr[N - 1] == 0) + /* Pseudo zero. */ + *expt = 0; ++ else ++ /* Unlike other floating point formats, the most significant bit ++ is explicit and expected to be set for normal numbers. Set it ++ in case it is cleared in the input. Otherwise, callers will ++ not be able to produce the expected multi-precision integer ++ layout by shifting. */ ++ res_ptr[N - 1] |= (mp_limb_t) 1 << (LDBL_MANT_DIG - 1 ++ - ((N - 1) * BITS_PER_MP_LIMB)); + + return N; + } +diff --git a/sysdeps/x86/tst-ldbl-nonnormal-printf.c b/sysdeps/x86/tst-ldbl-nonnormal-printf.c +new file mode 100644 +index 0000000000..54381ece0b +--- /dev/null ++++ b/sysdeps/x86/tst-ldbl-nonnormal-printf.c +@@ -0,0 +1,52 @@ ++/* Test printf with x86-specific non-normal long double value. ++ Copyright (C) 2020 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 ++ ++/* Fill the stack with non-zero values. This makes a crash in ++ snprintf more likely. */ ++static void __attribute__ ((noinline, noclone)) ++fill_stack (void) ++{ ++ char buffer[65536]; ++ memset (buffer, 0xc0, sizeof (buffer)); ++ asm ("" ::: "memory"); ++} ++ ++static int ++do_test (void) ++{ ++ fill_stack (); ++ ++ long double value; ++ memcpy (&value, "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x04", 10); ++ ++ char buf[30]; ++ int ret = snprintf (buf, sizeof (buf), "%Lg", value); ++ TEST_COMPARE (ret, strlen (buf)); ++ if (strcmp (buf, "nan") != 0) ++ /* If snprintf does not recognize the non-normal number as a NaN, ++ it has added the missing explicit MSB. */ ++ TEST_COMPARE_STRING (buf, "3.02201e-4624"); ++ return 0; ++} ++ ++#include +-- +2.23.0 + diff --git a/backport-Fix-iconv-buffer-handling-with-IGNORE-error-handler-.patch b/backport-Fix-iconv-buffer-handling-with-IGNORE-error-handler-.patch new file mode 100644 index 0000000000000000000000000000000000000000..110c5afb5d42728fac4fa49c36ea02db200edf9d --- /dev/null +++ b/backport-Fix-iconv-buffer-handling-with-IGNORE-error-handler-.patch @@ -0,0 +1,339 @@ +From 4802be92c891903caaf8cae47f685da6f26d4b9a Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Mon, 17 Aug 2015 14:05:01 +0200 +Subject: [PATCH] Fix iconv buffer handling with IGNORE error handler (bug + #18830) + +reason:Fix iconv buffer handling with IGNORE error handler +Conflict:NA +Reference:https://sourceware.org/bugzilla/show_bug.cgi?id=18830 + +--- + iconv/Makefile | 3 +- + iconv/gconv_simple.c | 32 ++++++++++------ + iconv/skeleton.c | 35 +++++++++++++---- + iconv/tst-iconv7.c | 55 +++++++++++++++++++++++++++ + sysdeps/s390/multiarch/gconv_simple.c | 6 +-- + 5 files changed, 108 insertions(+), 23 deletions(-) + create mode 100644 iconv/tst-iconv7.c + +diff --git a/iconv/Makefile b/iconv/Makefile +index e4d73376..73d983af 100644 +--- a/iconv/Makefile ++++ b/iconv/Makefile +@@ -43,7 +43,8 @@ CFLAGS-charmap.c += -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ + CFLAGS-linereader.c += -DNO_TRANSLITERATION + CFLAGS-simple-hash.c += -I../locale + +-tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 ++tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ ++ tst-iconv7 + + others = iconv_prog iconvconfig + others-pie += iconv_prog iconvconfig +diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c +index 506c92ca..c487b892 100644 +--- a/iconv/gconv_simple.c ++++ b/iconv/gconv_simple.c +@@ -76,7 +76,7 @@ __attribute ((always_inline)) + internal_ucs4_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, const unsigned char *outend, + size_t *irreversible) + { + const unsigned char *inptr = *inptrp; +@@ -120,7 +120,8 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + const unsigned char *inptr = *inptrp; +@@ -169,7 +170,8 @@ internal_ucs4_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + mbstate_t *state = step_data->__statep; +@@ -231,7 +233,7 @@ __attribute ((always_inline)) + ucs4_internal_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +@@ -298,7 +300,8 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +@@ -368,7 +371,8 @@ ucs4_internal_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + mbstate_t *state = step_data->__statep; +@@ -443,7 +447,7 @@ __attribute ((always_inline)) + internal_ucs4le_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, const unsigned char *outend, + size_t *irreversible) + { + const unsigned char *inptr = *inptrp; +@@ -488,7 +492,8 @@ internal_ucs4le_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + const unsigned char *inptr = *inptrp; +@@ -540,7 +545,8 @@ internal_ucs4le_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + mbstate_t *state = step_data->__statep; +@@ -601,7 +607,7 @@ __attribute ((always_inline)) + ucs4le_internal_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +@@ -671,7 +677,8 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +@@ -745,7 +752,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, + const unsigned char *inend, +- unsigned char **outptrp, unsigned char *outend, ++ unsigned char **outptrp, ++ const unsigned char *outend, + size_t *irreversible) + { + mbstate_t *state = step_data->__statep; +diff --git a/iconv/skeleton.c b/iconv/skeleton.c +index fa799305..f4e499e2 100644 +--- a/iconv/skeleton.c ++++ b/iconv/skeleton.c +@@ -83,6 +83,11 @@ + RESET_INPUT_BUFFER If the input character sets allow this the macro + can be defined to reset the input buffer pointers + to cover only those characters up to the error. ++ Note that if the conversion has skipped over ++ irreversible characters (due to ++ __GCONV_IGNORE_ERRORS) there is no longer a direct ++ correspondence between input and output pointers, ++ and this macro is not called. + + FUNCTION_NAME if not set the conversion function is named `gconv'. + +@@ -597,6 +602,12 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + inptr = *inptrp; + /* The outbuf buffer is empty. */ + outstart = outbuf; ++#ifdef RESET_INPUT_BUFFER ++ /* Remember how many irreversible characters were skipped before ++ this round. */ ++ size_t loop_irreversible ++ = lirreversible + (irreversible ? *irreversible : 0); ++#endif + + #ifdef SAVE_RESET_STATE + SAVE_RESET_STATE (1); +@@ -671,8 +682,16 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + if (__glibc_unlikely (outerr != outbuf)) + { + #ifdef RESET_INPUT_BUFFER +- RESET_INPUT_BUFFER; +-#else ++ /* RESET_INPUT_BUFFER can only work when there were ++ no new irreversible characters skipped during ++ this round. */ ++ if (loop_irreversible ++ == lirreversible + (irreversible ? *irreversible : 0)) ++ { ++ RESET_INPUT_BUFFER; ++ goto done_reset; ++ } ++#endif + /* We have a problem in one of the functions below. + Undo the conversion upto the error point. */ + size_t nstatus __attribute__ ((unused)); +@@ -682,9 +701,9 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + outbuf = outstart; + + /* Restore the state. */ +-# ifdef SAVE_RESET_STATE ++#ifdef SAVE_RESET_STATE + SAVE_RESET_STATE (0); +-# endif ++#endif + + if (__glibc_likely (!unaligned)) + { +@@ -701,7 +720,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + lirreversiblep + EXTRA_LOOP_ARGS); + } +-# if POSSIBLY_UNALIGNED ++#if POSSIBLY_UNALIGNED + else + { + if (FROM_DIRECTION) +@@ -720,7 +739,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + lirreversiblep + EXTRA_LOOP_ARGS); + } +-# endif ++#endif + + /* We must run out of output buffer space in this + rerun. */ +@@ -731,9 +750,11 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, + the invocation counter. */ + if (__glibc_unlikely (outbuf == outstart)) + --data->__invocation_counter; +-#endif /* reset input buffer */ + } + ++#ifdef RESET_INPUT_BUFFER ++ done_reset: ++#endif + /* Change the status. */ + status = result; + } +diff --git a/iconv/tst-iconv7.c b/iconv/tst-iconv7.c +new file mode 100644 +index 00000000..10372bf7 +--- /dev/null ++++ b/iconv/tst-iconv7.c +@@ -0,0 +1,55 @@ ++/* Test iconv buffer handling with the IGNORE error handler. ++ Copyright (C) 2019 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 ++ . */ ++ ++/* Derived from BZ #18830 */ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* This conversion needs two steps, from ASCII to INTERNAL to ASCII. */ ++ iconv_t cd = iconv_open ("ASCII//IGNORE", "ASCII"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* Convert some irreversible sequence, enough to trigger an overflow of ++ the output buffer before the irreversible character in the second ++ step, but after going past the irreversible character in the first ++ step. */ ++ char input[4 + 4] = { '0', '1', '2', '3', '4', '5', '\266', '7' }; ++ char *inptr = input; ++ size_t insize = sizeof (input); ++ char output[4]; ++ char *outptr = output; ++ size_t outsize = sizeof (output); ++ ++ /* The conversion should fail. */ ++ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); ++ TEST_VERIFY (errno == E2BIG); ++ /* The conversion should not consume more than it was able to store in ++ the output buffer. */ ++ TEST_COMPARE (inptr - input, sizeof (output) - outsize); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/s390/multiarch/gconv_simple.c b/sysdeps/s390/multiarch/gconv_simple.c +index aaa1ebf7..88772fab 100644 +--- a/sysdeps/s390/multiarch/gconv_simple.c ++++ b/sysdeps/s390/multiarch/gconv_simple.c +@@ -403,7 +403,7 @@ ICONV_VX_NAME (internal_ucs4le_loop) (struct __gconv_step *step, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, +- unsigned char *outend, ++ const unsigned char *outend, + size_t *irreversible) + { + const unsigned char *inptr = *inptrp; +@@ -503,7 +503,7 @@ ICONV_VX_NAME (ucs4_internal_loop) (struct __gconv_step *step, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, +- unsigned char *outend, ++ const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +@@ -630,7 +630,7 @@ ICONV_VX_NAME (ucs4le_internal_loop) (struct __gconv_step *step, + const unsigned char **inptrp, + const unsigned char *inend, + unsigned char **outptrp, +- unsigned char *outend, ++ const unsigned char *outend, + size_t *irreversible) + { + int flags = step_data->__flags; +-- +2.23.0 + diff --git a/backport-x86-Use-one-ldbl2mpn.c-file-for-both-i386-and-x86_64.patch b/backport-x86-Use-one-ldbl2mpn.c-file-for-both-i386-and-x86_64.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7e137dd96bd2371cde9352b150c7c76e19c7fac --- /dev/null +++ b/backport-x86-Use-one-ldbl2mpn.c-file-for-both-i386-and-x86_64.patch @@ -0,0 +1,34 @@ +From 90ccfdf17628e152d96638adc175ae97bd078cfc Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 22 Sep 2020 17:29:35 +0200 +Subject: [PATCH] x86: Use one ldbl2mpn.c file for both i386 and x86_64 + +--- + sysdeps/ia64/ldbl2mpn.c | 2 +- + sysdeps/{i386 => x86}/ldbl2mpn.c | 0 + sysdeps/x86_64/ldbl2mpn.c | 1 - + 3 files changed, 1 insertion(+), 2 deletions(-) + rename sysdeps/{i386 => x86}/ldbl2mpn.c (100%) + delete mode 100644 sysdeps/x86_64/ldbl2mpn.c + +diff --git a/sysdeps/ia64/ldbl2mpn.c b/sysdeps/ia64/ldbl2mpn.c +index 641b789cd4..66ac0a47a4 100644 +--- a/sysdeps/ia64/ldbl2mpn.c ++++ b/sysdeps/ia64/ldbl2mpn.c +@@ -1 +1 @@ +-#include "../i386/ldbl2mpn.c" ++#include "../x86/ldbl2mpn.c" +diff --git a/sysdeps/i386/ldbl2mpn.c b/sysdeps/x86/ldbl2mpn.c +similarity index 100% +rename from sysdeps/i386/ldbl2mpn.c +rename to sysdeps/x86/ldbl2mpn.c +diff --git a/sysdeps/x86_64/ldbl2mpn.c b/sysdeps/x86_64/ldbl2mpn.c +deleted file mode 100644 +index 641b789cd4..0000000000 +--- a/sysdeps/x86_64/ldbl2mpn.c ++++ /dev/null +@@ -1 +0,0 @@ +-#include "../i386/ldbl2mpn.c" +-- +2.23.0 + diff --git a/glibc.spec b/glibc.spec index cc2c2bddbdaa7646fc2ba977649f76ebefd42c31..795deb30d730667ed8967800ba4a8b1982b6f4ab 100644 --- a/glibc.spec +++ b/glibc.spec @@ -46,9 +46,9 @@ %endif %define enablekernel 3.2 -%define target %{_target_cpu}-%{_vendor}-linux +%define target %{_target_cpu}-openEuler-linux %ifarch %{arm} -%define target %{_target_cpu}-%{_vendor}-linuxeabi +%define target %{_target_cpu}-openEuler-linuxeabi %endif %define x86_arches %{ix86} x86_64 %define all_license LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL @@ -59,7 +59,7 @@ ############################################################################## Name: glibc Version: 2.28 -Release: 48 +Release: 49 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -97,6 +97,10 @@ Patch20: backport-0001-Fix-handling-of-collating-symbols-in-fnmatch-bug-266.patc Patch21: backport-sysvipc-Fix-SEM_STAT_ANY-kernel-argument-pass-BZ-26637.patch Patch22: backport-i686-tst-strftime3-fix-printf-warning.patch Patch23: Fix-CVE-2020-27618-iconv-Accept-redundant-shift-sequences.patch +Patch24: backport-x86-Use-one-ldbl2mpn.c-file-for-both-i386-and-x86_64.patch +Patch25: backport-Fix-CVE-2020-29573-x86-Harden-printf-against-non-normal-long-double-val.patch +Patch26: backport-Fix-iconv-buffer-handling-with-IGNORE-error-handler-.patch +Patch27: backport-CVE-2020-29562-iconv-Fix-incorrect-UCS4-inner-loop-bounds-BZ-26923.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1092,8 +1096,15 @@ fi %doc hesiod/README.hesiod %changelog -* Fri Jan 8 2021 Wang Shuo - 2.28-48 -- Replace "openEuler" by %{_vendor} for versatility +* Mon Dec 21 2020 Wang Shuo - 2.28-49 +- Fix CVE-2020-29562, Fix incorrect UCS4 inner loop bounds (BZ#26923) + https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-29562 + https://sourceware.org/bugzilla/show_bug.cgi?id=26923 + +* Thu Dec 17 2020 Wang Shuo - 2.28-48 +- Fix CVE-2020-29573, Harden printf against non-normal long double values + https://cve.mitre.org/cgi-bin/cvename.cgi?name=2020-29573 + https://sourceware.org/bugzilla/show_bug.cgi?id=26649 * Tue Nov 10 2020 liusirui - 2.28-47 - Fix CVE-2020-27618, iconv accept redundant shift sequences in IBM1364 [BZ #26224]