From 79e8c432c22c96c4edcd8f7cf8d311f66462a93e Mon Sep 17 00:00:00 2001 From: Shuo Wang Date: Thu, 17 Dec 2020 14:41:24 +0800 Subject: [PATCH] Fix CVE-2020-29573, Harden printf against non-normal long double values --- ...f-against-non-normal-long-double-val.patch | 128 ++++++++++++++++++ ...2mpn.c-file-for-both-i386-and-x86_64.patch | 34 +++++ glibc.spec | 9 +- 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 backport-Fix-CVE-2020-29573-x86-Harden-printf-against-non-normal-long-double-val.patch create mode 100644 backport-x86-Use-one-ldbl2mpn.c-file-for-both-i386-and-x86_64.patch 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 0000000..ff88c28 --- /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-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 0000000..d7e137d --- /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 048db7c..4708bc2 100644 --- a/glibc.spec +++ b/glibc.spec @@ -59,7 +59,7 @@ ############################################################################## Name: glibc Version: 2.28 -Release: 47 +Release: 48 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -97,6 +97,8 @@ 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 Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1092,6 +1094,11 @@ fi %doc hesiod/README.hesiod %changelog +* 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] https://sourceware.org/bugzilla/show_bug.cgi?id=26224 -- Gitee