Hello community, here is the log from the commit of package glibc for openSUSE:Leap:15.2 checked in at 2020-03-20 05:52:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/glibc (Old) and /work/SRC/openSUSE:Leap:15.2/.glibc.new.3160 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "glibc" Fri Mar 20 05:52:42 2020 rev:71 rq:785107 version:2.26 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/glibc/glibc.changes 2020-02-16 18:25:25.206627021 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.glibc.new.3160/glibc.changes 2020-03-20 05:52:54.200063360 +0100 @@ -1,0 +2,14 @@ +Thu Mar 5 13:05:23 UTC 2020 - Andreas Schwab <sch...@suse.de> + +- 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 25 10:22:28 UTC 2020 - Andreas Schwab <sch...@suse.de> + +- pthread-rwlock-pwn.patch: Fix rwlock stall with + PREFER_WRITER_NONRECURSIVE_NP (bsc#1164505, BZ #23861) +- manual-memory-protection.patch: manual: Document mprotect and introduce + section on memory protection (bsc#1163184) + +------------------------------------------------------------------- New: ---- ldbl-96-rem-pio2l.patch manual-memory-protection.patch pthread-rwlock-pwn.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ glibc.spec ++++++ --- /var/tmp/diff_new_pack.QNXOS2/_old 2020-03-20 05:52:56.900065158 +0100 +++ /var/tmp/diff_new_pack.QNXOS2/_new 2020-03-20 05:52:56.900065158 +0100 @@ -419,6 +419,12 @@ Patch1074: glibc-2.29-posix-Use-posix_spawn-on-popen.patch # PATCH-FIX-UPSTREAM Fix array overflow in backtrace on PowerPC (BZ #25423) Patch1075: backtrace-powerpc.patch +# PATCH-FIX-UPSTREAM Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (BZ #23861) +Patch1076: pthread-rwlock-pwn.patch +# PATCH-FIX-UPSTREAM manual: Document mprotect and introduce section on memory protection +Patch1077: manual-memory-protection.patch +# PATCH-FIX-UPSTREAM Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (CVE-2020-10029, BZ #25487) +Patch1078: ldbl-96-rem-pio2l.patch ### # Patches awaiting upstream approval @@ -729,6 +735,9 @@ %patch1073 -p1 %patch1074 -p1 %patch1075 -p1 +%patch1076 -p1 +%patch1077 -p1 +%patch1078 -p1 %patch2000 -p1 %patch2001 -p1 ++++++ ldbl-96-rem-pio2l.patch ++++++ >From 9333498794cde1d5cca518badf79533a24114b6f Mon Sep 17 00:00:00 2001 From: Joseph Myers <jos...@codesourcery.com> 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. --- sysdeps/ieee754/ldbl-96/Makefile | 3 +- sysdeps/ieee754/ldbl-96/e_rem_pio2l.c | 12 +++++++ sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c | 41 ++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c Index: glibc-2.26/sysdeps/ieee754/ldbl-96/Makefile =================================================================== --- glibc-2.26.orig/sysdeps/ieee754/ldbl-96/Makefile +++ glibc-2.26/sysdeps/ieee754/ldbl-96/Makefile @@ -17,5 +17,8 @@ # <http://www.gnu.org/licenses/>. ifeq ($(subdir),math) -tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 +tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo +ifeq ($(have-ssp),yes) +CFLAGS-test-sinl-pseudo.c += -fstack-protector-all endif +endif # $(subdir) == math Index: glibc-2.26/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c =================================================================== --- glibc-2.26.orig/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +++ glibc-2.26/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.26/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c =================================================================== --- /dev/null +++ glibc-2.26/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 + <https://www.gnu.org/licenses/>. */ + +#include <math.h> +#include <math_ldbl.h> +#include <stdint.h> + +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 <support/test-driver.c> ++++++ manual-memory-protection.patch ++++++ 2017-11-19 Florian Weimer <fwei...@redhat.com> manual: Document mprotect * manual/memory.texi (Memory Protection): New section. * manual/llio.texi (Memory-mapped I/O): Remove duplicate documentation of PROT_* flags and reference the Memory Protection section instead. Index: glibc-2.26/manual/llio.texi =================================================================== --- glibc-2.26.orig/manual/llio.texi +++ glibc-2.26/manual/llio.texi @@ -1411,19 +1411,11 @@ is created, which is not removed by clos address is automatically removed. The address you give may still be changed, unless you use the @code{MAP_FIXED} flag. -@vindex PROT_READ -@vindex PROT_WRITE -@vindex PROT_EXEC @var{protect} contains flags that control what kind of access is permitted. They include @code{PROT_READ}, @code{PROT_WRITE}, and -@code{PROT_EXEC}, which permit reading, writing, and execution, -respectively. Inappropriate access will cause a segfault (@pxref{Program -Error Signals}). - -Note that most hardware designs cannot support write permission without -read permission, and many do not distinguish read and execute permission. -Thus, you may receive wider permissions than you ask for, and mappings of -write-only files may be denied even if you do not use @code{PROT_READ}. +@code{PROT_EXEC}. The special flag @code{PROT_NONE} reserves a region +of address space for future use. The @code{mprotect} function can be +used to change the protection flags. @xref{Memory Protection}. @var{flags} contains flags that control the nature of the map. One of @code{MAP_SHARED} or @code{MAP_PRIVATE} must be specified. Index: glibc-2.26/manual/memory.texi =================================================================== --- glibc-2.26.orig/manual/memory.texi +++ glibc-2.26/manual/memory.texi @@ -17,6 +17,7 @@ and allocation of real memory. * Memory Concepts:: An introduction to concepts and terminology. * Memory Allocation:: Allocating storage for your program data * Resizing the Data Segment:: @code{brk}, @code{sbrk} +* Memory Protection:: Controlling access to memory regions. * Locking Pages:: Preventing page faults @end menu @@ -3050,7 +3051,128 @@ of the data segment is. @end deftypefun +@node Memory Protection +@section Memory Protection +@cindex memory protection +@cindex page protection +@cindex protection flags + +When a page is mapped using @code{mmap}, page protection flags can be +specified using the protection flags argument. @xref{Memory-mapped +I/O}. +The following flags are available: + +@vtable @code +@item PROT_WRITE +@standards{POSIX, sys/mman.h} +The memory can be written to. + +@item PROT_READ +@standards{POSIX, sys/mman.h} +The memory can be read. On some architectures, this flag implies that +the memory can be executed as well (as if @code{PROT_EXEC} had been +specified at the same time). + +@item PROT_EXEC +@standards{POSIX, sys/mman.h} +The memory can be used to store instructions which can then be executed. +On most architectures, this flag implies that the memory can be read (as +if @code{PROT_READ} had been specified). + +@item PROT_NONE +@standards{POSIX, sys/mman.h} +This flag must be specified on its own. + +The memory is reserved, but cannot be read, written, or executed. If +this flag is specified in a call to @code{mmap}, a virtual memory area +will be set aside for future use in the process, and @code{mmap} calls +without the @code{MAP_FIXED} flag will not use it for subsequent +allocations. For anonymous mappings, the kernel will not reserve any +physical memory for the allocation at the time the mapping is created. +@end vtable + +The operating system may keep track of these flags separately even if +the underlying hardware treats them the same for the purposes of access +checking (as happens with @code{PROT_READ} and @code{PROT_EXEC} on some +platforms). On GNU systems, @code{PROT_EXEC} always implies +@code{PROT_READ}, so that users can view the machine code which is +executing on their system. + +Inappropriate access will cause a segfault (@pxref{Program Error +Signals}). + +After allocation, protection flags can be changed using the +@code{mprotect} function. + +@deftypefun int mprotect (void *@var{address}, size_t @var{length}, int @var{protection}) +@standards{POSIX, sys/mman.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + +A successful call to the @code{mprotect} function changes the protection +flags of at least @var{length} bytes of memory, starting at +@var{address}. + +@var{address} must be aligned to the page size for the mapping. The +system page size can be obtained by calling @code{sysconf} with the +@code{_SC_PAGESIZE} parameter (@pxref{Sysconf Definition}). The system +page size is the granularity in which the page protection of anonymous +memory mappings and most file mappings can be changed. Memory which is +mapped from special files or devices may have larger page granularity +than the system page size and may require larger alignment. + +@var{length} is the number of bytes whose protection flags must be +changed. It is automatically rounded up to the next multiple of the +system page size. + +@var{protection} is a combination of the @code{PROT_*} flags described +above. + +The @code{mprotect} function returns @math{0} on success and @math{-1} +on failure. + +The following @code{errno} error conditions are defined for this +function: + +@table @code +@item ENOMEM +The system was not able to allocate resources to fulfill the request. +This can happen if there is not enough physical memory in the system for +the allocation of backing storage. The error can also occur if the new +protection flags would cause the memory region to be split from its +neighbors, and the process limit for the number of such distinct memory +regions would be exceeded. + +@item EINVAL +@var{address} is not properly aligned to a page boundary for the +mapping, or @var{length} (after rounding up to the system page size) is +not a multiple of the applicable page size for the mapping, or the +combination of flags in @var{protection} is not valid. + +@item EACCES +The file for a file-based mapping was not opened with open flags which +are compatible with @var{protection}. + +@item EPERM +The system security policy does not allow a mapping with the specified +flags. For example, mappings which are both @code{PROT_EXEC} and +@code{PROT_WRITE} at the same time might not be allowed. +@end table +@end deftypefun + +If the @code{mprotect} function is used to make a region of memory +inaccessible by specifying the @code{PROT_NONE} protection flag and +access is later restored, the memory retains its previous contents. + +On some systems, it may not be possible to specify additional flags +which were not present when the mapping was first created. For example, +an attempt to make a region of memory executable could fail if the +initial protection flags were @samp{PROT_READ | PROT_WRITE}. + +In general, the @code{mprotect} function can be used to change any +process memory, no matter how it was allocated. However, portable use +of the function requires that it is only used with memory regions +returned by @code{mmap} or @code{mmap64}. @node Locking Pages @section Locking Pages ++++++ pthread-rwlock-pwn.patch ++++++ 2018-12-13 Andreas Schwab <sch...@suse.de> [BZ #23861] * nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Update expected value for __readers while waiting on PTHREAD_RWLOCK_RWAITING. * nptl/tst-rwlock-pwn.c: New file. * nptl/Makefile (tests): Add tst-rwlock-pwn. Index: glibc-2.26/nptl/Makefile =================================================================== --- glibc-2.26.orig/nptl/Makefile +++ glibc-2.26/nptl/Makefile @@ -302,7 +302,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 ts c89 gnu89 c99 gnu99 c11 gnu11) \ tst-bad-schedattr \ tst-thread_local1 tst-mutex-errorcheck tst-robust10 \ - tst-robust-fork tst-create-detached tst-memstream + tst-robust-fork tst-create-detached tst-memstream \ + tst-rwlock-pwn tests-internal := tst-typesizes \ tst-rwlock19 tst-rwlock20 \ Index: glibc-2.26/nptl/pthread_rwlock_common.c =================================================================== --- glibc-2.26.orig/nptl/pthread_rwlock_common.c +++ glibc-2.26/nptl/pthread_rwlock_common.c @@ -314,7 +314,7 @@ __pthread_rwlock_rdlock_full (pthread_rw harmless because the flag is just about the state of __readers, and all threads set the flag under the same conditions. */ - while ((atomic_load_relaxed (&rwlock->__data.__readers) + while (((r = atomic_load_relaxed (&rwlock->__data.__readers)) & PTHREAD_RWLOCK_RWAITING) != 0) { int private = __pthread_rwlock_get_private (rwlock); Index: glibc-2.26/nptl/tst-rwlock-pwn.c =================================================================== --- /dev/null +++ glibc-2.26/nptl/tst-rwlock-pwn.c @@ -0,0 +1,87 @@ +/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861). + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <support/xthread.h> + +/* We choose 10 iterations because this happens to be able to trigger the + stall on contemporary hardware. */ +#define LOOPS 10 +/* We need 3 threads to trigger bug 23861. One thread as a writer, and + two reader threads. The test verifies that the second-to-last reader + is able to notify the *last* reader that it should be done waiting. + If the second-to-last reader fails to notify the last reader or does + so incorrectly then the last reader may stall indefinitely. */ +#define NTHREADS 3 + +_Atomic int do_exit; +pthread_rwlockattr_t mylock_attr; +pthread_rwlock_t mylock; + +void * +run_loop (void *a) +{ + while (!do_exit) + { + if (random () & 1) + { + xpthread_rwlock_wrlock (&mylock); + xpthread_rwlock_unlock (&mylock); + } + else + { + xpthread_rwlock_rdlock (&mylock); + xpthread_rwlock_unlock (&mylock); + } + } + return NULL; +} + +int +do_test (void) +{ + xpthread_rwlockattr_init (&mylock_attr); + xpthread_rwlockattr_setkind_np (&mylock_attr, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + xpthread_rwlock_init (&mylock, &mylock_attr); + + for (int n = 0; n < LOOPS; n++) + { + pthread_t tids[NTHREADS]; + do_exit = 0; + for (int i = 0; i < NTHREADS; i++) + tids[i] = xpthread_create (NULL, run_loop, NULL); + /* Let the threads run for some time. */ + sleep (1); + printf ("Exiting..."); + fflush (stdout); + do_exit = 1; + for (int i = 0; i < NTHREADS; i++) + xpthread_join (tids[i]); + printf ("done.\n"); + } + pthread_rwlock_destroy (&mylock); + pthread_rwlockattr_destroy (&mylock_attr); + return 0; +} + +#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS) +#include <support/test-driver.c>