From 128ba887d3869e5f518abb3bc956d03be093ee551b3aaa8ab8f7738653b41f73 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Thu, 12 Mar 2020 16:18:04 +0000 Subject: [PATCH] Accepting request 784366 from home:Andreas_Schwab:Factory - riscv-syscall-clobber.patch: riscv: Avoid clobbering register parameters in syscall - ldbl-96-rem-pio2l.patch: Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (CVE-2020-10029, bsc#1165784, BZ #25487) OBS-URL: https://build.opensuse.org/request/show/784366 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=554 --- _constraints | 5 +- glibc.changes | 8 ++ glibc.spec | 7 ++ ldbl-96-rem-pio2l.patch | 123 ++++++++++++++++++++++++ riscv-syscall-clobber.patch | 181 ++++++++++++++++++++++++++++++++++++ 5 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 ldbl-96-rem-pio2l.patch create mode 100644 riscv-syscall-clobber.patch diff --git a/_constraints b/_constraints index 03d38d4..f8ea62c 100644 --- a/_constraints +++ b/_constraints @@ -2,12 +2,15 @@ - glibc-testsuite + glibc:testsuite 1500 + + 5600 + xen diff --git a/glibc.changes b/glibc.changes index 1b04661..fbb08f8 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Mar 12 10:21:15 UTC 2020 - Andreas Schwab + +- riscv-syscall-clobber.patch: riscv: Avoid clobbering register parameters + in syscall +- ldbl-96-rem-pio2l.patch: Avoid ldbl-96 stack corruption from range + reduction of pseudo-zero (CVE-2020-10029, bsc#1165784, BZ #25487) + ------------------------------------------------------------------- Tue Feb 18 12:41:56 UTC 2020 - Andreas Schwab diff --git a/glibc.spec b/glibc.spec index d26648a..14c0e89 100644 --- a/glibc.spec +++ b/glibc.spec @@ -257,6 +257,10 @@ Patch306: glibc-fix-double-loopback.diff ### # Patches from upstream ### +# PATCH-FIX-UPSTREAM riscv: Avoid clobbering register parameters in syscall +Patch1000: riscv-syscall-clobber.patch +# PATCH-FIX-UPSTREAM Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (CVE-2020-10029, BZ #25487) +Patch1001: ldbl-96-rem-pio2l.patch ### # Patches awaiting upstream approval @@ -464,6 +468,9 @@ makedb: A program to create a database for nss %patch304 -p1 %patch306 -p1 +%patch1000 -p1 +%patch1001 -p1 + %patch2000 -p1 %patch2001 -p1 %patch2002 -p1 diff --git a/ldbl-96-rem-pio2l.patch b/ldbl-96-rem-pio2l.patch new file mode 100644 index 0000000..68dd6c2 --- /dev/null +++ b/ldbl-96-rem-pio2l.patch @@ -0,0 +1,123 @@ +From 9f997ceca28f0634ad78a1ca95b84265f7801ff4 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Wed, 12 Feb 2020 23:31:56 +0000 +Subject: [PATCH] Avoid ldbl-96 stack corruption from range reduction of + pseudo-zero (bug 25487). + +Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero +argument (an representation where all the significand bits, including +the explicit high bit, are zero, but the exponent is not zero, which +is not a valid representation for the long double type). + +Although this is not a valid long double representation, existing +practice in this area (see bug 4586, originally marked invalid but +subsequently fixed) is that we still seek to avoid invalid memory +accesses as a result, in case of programs that treat arbitrary binary +data as long double representations, although the invalid +representations of the ldbl-96 format do not need to be consistently +handled the same as any particular valid representation. + +This patch makes the range reduction detect pseudo-zero and unnormal +representations that would otherwise go to __kernel_rem_pio2, and +returns a NaN for them instead of continuing with the range reduction +process. (Pseudo-zero and unnormal representations whose unbiased +exponent is less than -1 have already been safely returned from the +function before this point without going through the rest of range +reduction.) Pseudo-zero representations would previously result in +the value passed to __kernel_rem_pio2 being all-zero, which is +definitely unsafe; unnormal representations would previously result in +a value passed whose high bit is zero, which might well be unsafe +since that is not a form of input expected by __kernel_rem_pio2. + +Tested for x86_64. + +(cherry picked from commit 9333498794cde1d5cca518badf79533a24114b6f) +--- + NEWS | 5 +++ + sysdeps/ieee754/ldbl-96/Makefile | 3 +- + sysdeps/ieee754/ldbl-96/e_rem_pio2l.c | 12 +++++++ + sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c | 41 ++++++++++++++++++++++ + 4 files changed, 60 insertions(+), 1 deletion(-) + create mode 100644 sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c + +Index: glibc-2.31/sysdeps/ieee754/ldbl-96/Makefile +=================================================================== +--- glibc-2.31.orig/sysdeps/ieee754/ldbl-96/Makefile ++++ glibc-2.31/sysdeps/ieee754/ldbl-96/Makefile +@@ -17,5 +17,6 @@ + # . + + ifeq ($(subdir),math) +-tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 ++tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo ++CFLAGS-test-sinl-pseudo.c += -fstack-protector-all + endif +Index: glibc-2.31/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +=================================================================== +--- glibc-2.31.orig/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c ++++ glibc-2.31/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +@@ -210,6 +210,18 @@ __ieee754_rem_pio2l (long double x, long + return 0; + } + ++ if ((i0 & 0x80000000) == 0) ++ { ++ /* Pseudo-zero and unnormal representations are not valid ++ representations of long double. We need to avoid stack ++ corruption in __kernel_rem_pio2, which expects input in a ++ particular normal form, but those representations do not need ++ to be consistently handled like any particular floating-point ++ value. */ ++ y[1] = y[0] = __builtin_nanl (""); ++ return 0; ++ } ++ + /* Split the 64 bits of the mantissa into three 24-bit integers + stored in a double array. */ + exp = j0 - 23; +Index: glibc-2.31/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c +=================================================================== +--- /dev/null ++++ glibc-2.31/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c +@@ -0,0 +1,41 @@ ++/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487). ++ 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 ++ ++static int ++do_test (void) ++{ ++ for (int i = 0; i < 64; i++) ++ { ++ uint64_t sig = i == 63 ? 0 : 1ULL << i; ++ long double ld; ++ SET_LDOUBLE_WORDS (ld, 0x4141, ++ sig >> 32, sig & 0xffffffffULL); ++ /* The requirement is that no stack overflow occurs when the ++ pseudo-zero or unnormal goes through range reduction. */ ++ volatile long double ldr; ++ ldr = sinl (ld); ++ (void) ldr; ++ } ++ return 0; ++} ++ ++#include diff --git a/riscv-syscall-clobber.patch b/riscv-syscall-clobber.patch new file mode 100644 index 0000000..ce65e3d --- /dev/null +++ b/riscv-syscall-clobber.patch @@ -0,0 +1,181 @@ +From be74b42ee2a97009a6cd4fc90126add4a41c583b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 10 Feb 2020 10:32:14 -0300 +Subject: [PATCH] riscv: Avoid clobbering register parameters in syscall + +The riscv INTERNAL_SYSCALL macro might clobber the register +parameter if the argument itself might clobber any register (a function +call for instance). + +This patch fixes it by using temporary variables for the expressions +between the register assignments (as indicated by GCC documentation, +6.47.5.2 Specifying Registers for Local Variables). + +It is similar to the fix done for MIPS (bug 25523). + +Checked with riscv64-linux-gnu-rv64imafdc-lp64d build. +--- + sysdeps/unix/sysv/linux/riscv/sysdep.h | 84 +++++++++++++++++--------- + 1 file changed, 56 insertions(+), 28 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h +index 201bf9a91b..2bd9b16f32 100644 +--- a/sysdeps/unix/sysv/linux/riscv/sysdep.h ++++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h +@@ -176,10 +176,11 @@ + # define internal_syscall1(number, err, arg0) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ ++ register long int __a0 asm ("a0") = _arg0; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -193,11 +194,13 @@ + # define internal_syscall2(number, err, arg0, arg1) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -211,12 +214,15 @@ + # define internal_syscall3(number, err, arg0, arg1, arg2) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ ++ long int _arg2 = (long int) (arg2); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ +- register long int __a2 asm ("a2") = (long int) (arg2); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ ++ register long int __a2 asm ("a2") = _arg2; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -230,13 +236,17 @@ + # define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ ++ long int _arg2 = (long int) (arg2); \ ++ long int _arg3 = (long int) (arg3); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ +- register long int __a2 asm ("a2") = (long int) (arg2); \ +- register long int __a3 asm ("a3") = (long int) (arg3); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ ++ register long int __a2 asm ("a2") = _arg2; \ ++ register long int __a3 asm ("a3") = _arg3; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -250,14 +260,19 @@ + # define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ ++ long int _arg2 = (long int) (arg2); \ ++ long int _arg3 = (long int) (arg3); \ ++ long int _arg4 = (long int) (arg4); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ +- register long int __a2 asm ("a2") = (long int) (arg2); \ +- register long int __a3 asm ("a3") = (long int) (arg3); \ +- register long int __a4 asm ("a4") = (long int) (arg4); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ ++ register long int __a2 asm ("a2") = _arg2; \ ++ register long int __a3 asm ("a3") = _arg3; \ ++ register long int __a4 asm ("a4") = _arg4; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -271,15 +286,21 @@ + # define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ ++ long int _arg2 = (long int) (arg2); \ ++ long int _arg3 = (long int) (arg3); \ ++ long int _arg4 = (long int) (arg4); \ ++ long int _arg5 = (long int) (arg5); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ +- register long int __a2 asm ("a2") = (long int) (arg2); \ +- register long int __a3 asm ("a3") = (long int) (arg3); \ +- register long int __a4 asm ("a4") = (long int) (arg4); \ +- register long int __a5 asm ("a5") = (long int) (arg5); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ ++ register long int __a2 asm ("a2") = _arg2; \ ++ register long int __a3 asm ("a3") = _arg3; \ ++ register long int __a4 asm ("a4") = _arg4; \ ++ register long int __a5 asm ("a5") = _arg5; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +@@ -294,16 +315,23 @@ + # define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ + ({ \ + long int _sys_result; \ ++ long int _arg0 = (long int) (arg0); \ ++ long int _arg1 = (long int) (arg1); \ ++ long int _arg2 = (long int) (arg2); \ ++ long int _arg3 = (long int) (arg3); \ ++ long int _arg4 = (long int) (arg4); \ ++ long int _arg5 = (long int) (arg5); \ ++ long int _arg6 = (long int) (arg6); \ + \ + { \ + register long int __a7 asm ("a7") = number; \ +- register long int __a0 asm ("a0") = (long int) (arg0); \ +- register long int __a1 asm ("a1") = (long int) (arg1); \ +- register long int __a2 asm ("a2") = (long int) (arg2); \ +- register long int __a3 asm ("a3") = (long int) (arg3); \ +- register long int __a4 asm ("a4") = (long int) (arg4); \ +- register long int __a5 asm ("a5") = (long int) (arg5); \ +- register long int __a6 asm ("a6") = (long int) (arg6); \ ++ register long int __a0 asm ("a0") = _arg0; \ ++ register long int __a1 asm ("a1") = _arg1; \ ++ register long int __a2 asm ("a2") = _arg2; \ ++ register long int __a3 asm ("a3") = _arg3; \ ++ register long int __a4 asm ("a4") = _arg4; \ ++ register long int __a5 asm ("a5") = _arg5; \ ++ register long int __a6 asm ("a6") = _arg6; \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ +-- +2.25.1 +