diff --git a/srcpkgs/glibc/patches/glibc-upstream-01.patch b/srcpkgs/glibc/patches/glibc-upstream-01.patch new file mode 100644 index 00000000000..fa8a85a2026 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-01.patch @@ -0,0 +1,681 @@ +From 86013ef5cea322b8f4b9c22f230c22cce369e947 Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell +Date: Mon, 21 Jan 2019 22:50:12 -0500 +Subject: [PATCH 01] nptl: Fix pthread_rwlock_try*lock stalls (Bug 23844) + +For a full analysis of both the pthread_rwlock_tryrdlock() stall +and the pthread_rwlock_trywrlock() stall see: +https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14 + +In the pthread_rwlock_trydlock() function we fail to inspect for +PTHREAD_RWLOCK_FUTEX_USED in __wrphase_futex and wake the waiting +readers. + +In the pthread_rwlock_trywrlock() function we write 1 to +__wrphase_futex and loose the setting of the PTHREAD_RWLOCK_FUTEX_USED +bit, again failing to wake waiting readers during unlock. + +The fix in the case of pthread_rwlock_trydlock() is to check for +PTHREAD_RWLOCK_FUTEX_USED and wake the readers. + +The fix in the case of pthread_rwlock_trywrlock() is to only write +1 to __wrphase_futex if we installed the write phase, since all other +readers would be spinning waiting for this step. + +We add two new tests, one exercises the stall for +pthread_rwlock_trywrlock() which is easy to exercise, and one exercises +the stall for pthread_rwlock_trydlock() which is harder to exercise. + +The pthread_rwlock_trywrlock() test fails consistently without the fix, +and passes after. The pthread_rwlock_tryrdlock() test fails roughly +5-10% of the time without the fix, and passes all the time after. + +Signed-off-by: Carlos O'Donell +Signed-off-by: Torvald Riegel +Signed-off-by: Rik Prohaska +Co-authored-by: Torvald Riegel +Co-authored-by: Rik Prohaska +(cherry picked from commit 5fc9ed4c4058bfbdf51ad6e7aac7d209b580e8c4) +--- + ChangeLog | 17 ++ + nptl/Makefile | 3 +- + nptl/pthread_rwlock_tryrdlock.c | 25 ++- + nptl/pthread_rwlock_trywrlock.c | 9 +- + nptl/tst-rwlock-tryrdlock-stall.c | 355 ++++++++++++++++++++++++++++++ + nptl/tst-rwlock-trywrlock-stall.c | 108 +++++++++ + support/Makefile | 1 + + support/xpthread_rwlock_destroy.c | 26 +++ + support/xthread.h | 1 + + 9 files changed, 534 insertions(+), 11 deletions(-) + create mode 100644 nptl/tst-rwlock-tryrdlock-stall.c + create mode 100644 nptl/tst-rwlock-trywrlock-stall.c + create mode 100644 support/xpthread_rwlock_destroy.c + +diff --git a/ChangeLog b/ChangeLog +index 59dab18463..adb4e719a6 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,20 @@ ++2019-01-31 Carlos O'Donell ++ Torvald Riegel ++ Rik Prohaska ++ ++ [BZ# 23844] ++ * nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and ++ tst-rwlock-trywrlock-stall. ++ * nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock): ++ Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set. ++ * nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): ++ Set __wrphase_fute to 1 only if we started the write phase. ++ * nptl/tst-rwlock-tryrdlock-stall.c: New file. ++ * nptl/tst-rwlock-trywrlock-stall.c: New file. ++ * support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy. ++ * support/xpthread_rwlock_destroy.c: New file. ++ * support/xthread.h: Declare xpthread_rwlock_destroy. ++ + 2019-01-31 Siddhesh Poyarekar + + * version.h (RELEASE): Set to "stable". +diff --git a/nptl/Makefile b/nptl/Makefile +index 340282c6cb..0e316edfac 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -319,7 +319,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \ + tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \ +- tst-rwlock-pwn ++ tst-rwlock-pwn \ ++ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall + + tests-internal := tst-rwlock19 tst-rwlock20 \ + tst-sem11 tst-sem12 tst-sem13 \ +diff --git a/nptl/pthread_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c +index 368862ff07..2f94f17f36 100644 +--- a/nptl/pthread_rwlock_tryrdlock.c ++++ b/nptl/pthread_rwlock_tryrdlock.c +@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) + /* Same as in __pthread_rwlock_rdlock_full: + We started the read phase, so we are also responsible for + updating the write-phase futex. Relaxed MO is sufficient. +- Note that there can be no other reader that we have to wake +- because all other readers will see the read phase started by us +- (or they will try to start it themselves); if a writer started +- the read phase, we cannot have started it. Furthermore, we +- cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will +- overwrite the value set by the most recent writer (or the readers +- before it in case of explicit hand-over) and we know that there +- are no waiting readers. */ +- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0); ++ We have to do the same steps as a writer would when handing over the ++ read phase to use because other readers cannot distinguish between ++ us and the writer. ++ Note that __pthread_rwlock_tryrdlock callers will not have to be ++ woken up because they will either see the read phase started by us ++ or they will try to start it themselves; however, callers of ++ __pthread_rwlock_rdlock_full just increase the reader count and then ++ check what state the lock is in, so they cannot distinguish between ++ us and a writer that acquired and released the lock in the ++ meantime. */ ++ if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0) ++ & PTHREAD_RWLOCK_FUTEX_USED) != 0) ++ { ++ int private = __pthread_rwlock_get_private (rwlock); ++ futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private); ++ } + } + + return 0; +diff --git a/nptl/pthread_rwlock_trywrlock.c b/nptl/pthread_rwlock_trywrlock.c +index fd37a71ce4..fae475cc70 100644 +--- a/nptl/pthread_rwlock_trywrlock.c ++++ b/nptl/pthread_rwlock_trywrlock.c +@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) + &rwlock->__data.__readers, &r, + r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED)) + { ++ /* We have become the primary writer and we cannot have shared ++ the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we ++ can simply enable blocking (see full wrlock code). */ + atomic_store_relaxed (&rwlock->__data.__writers_futex, 1); +- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); ++ /* If we started a write phase, we need to enable readers to ++ wait. If we did not, we must not change it because other threads ++ may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */ ++ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) ++ atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); + atomic_store_relaxed (&rwlock->__data.__cur_writer, + THREAD_GETMEM (THREAD_SELF, tid)); + return 0; +diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c +new file mode 100644 +index 0000000000..5e476da2b8 +--- /dev/null ++++ b/nptl/tst-rwlock-tryrdlock-stall.c +@@ -0,0 +1,355 @@ ++/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls. ++ 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 ++ . */ ++ ++/* For a full analysis see comment: ++ https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14 ++ ++ Provided here for reference: ++ ++ --- Analysis of pthread_rwlock_tryrdlock() stall --- ++ A read lock begins to execute. ++ ++ In __pthread_rwlock_rdlock_full: ++ ++ We can attempt a read lock, but find that the lock is ++ in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit ++ is set), and the lock is held by a primary writer ++ (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must ++ wait for explicit hand over from the writer to us or ++ one of the other waiters. The read lock threads are ++ about to execute: ++ ++ 341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers, ++ 342 (1 << PTHREAD_RWLOCK_READER_SHIFT)) ++ 343 + (1 << PTHREAD_RWLOCK_READER_SHIFT)); ++ ++ An unlock beings to execute. ++ ++ Then in __pthread_rwlock_wrunlock: ++ ++ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers); ++ ... ++ 549 while (!atomic_compare_exchange_weak_release ++ 550 (&rwlock->__data.__readers, &r, ++ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED) ++ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 ++ 553 : PTHREAD_RWLOCK_WRPHASE)))) ++ 554 { ++ ... ++ 556 } ++ ++ We clear PTHREAD_RWLOCK_WRLOCKED, and if there are ++ no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE. ++ ++ Back in the read lock. ++ ++ The read lock adjusts __readres as above. ++ ++ 383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0 ++ 384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0) ++ 385 { ++ ... ++ 390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r, ++ 391 r ^ PTHREAD_RWLOCK_WRPHASE)) ++ 392 { ++ ++ And then attemps to start the read phase. ++ ++ Assume there happens to be a tryrdlock at this point, noting ++ that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE ++ is 1. So the try lock attemps to start the read phase. ++ ++ In __pthread_rwlock_tryrdlock: ++ ++ 44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) ++ 45 { ++ ... ++ 49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0) ++ 50 && (rwlock->__data.__flags ++ 51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) ++ 52 return EBUSY; ++ 53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT); ++ 54 } ++ ... ++ 89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, ++ 90 &r, rnew)); ++ ++ And succeeds. ++ ++ Back in the write unlock: ++ ++ 557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0) ++ 558 { ++ ... ++ 563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0) ++ 564 & PTHREAD_RWLOCK_FUTEX_USED) != 0) ++ 565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private); ++ 566 } ++ ++ We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero ++ and don't wake anyone. This is OK because we handed ++ over to the trylock. It will be the trylock's responsibility ++ to wake any waiters. ++ ++ Back in the read lock: ++ ++ The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because ++ the __readers value was adjusted by the trylock, and so it falls through ++ to waiting on the lock for explicit handover from either a new writer ++ or a new reader. ++ ++ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, ++ 449 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ 450 abstime, private); ++ ++ We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex ++ is in use. ++ ++ At this point we have readers waiting on the read lock ++ to unlock. The wrlock is done. The trylock is finishing ++ the installation of the read phase. ++ ++ 92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0) ++ 93 { ++ ... ++ 105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0); ++ 106 } ++ ++ The trylock does note that we were the one that ++ installed the read phase, but the comments are not ++ correct, the execution ordering above shows that ++ readers might indeed be waiting, and they are. ++ ++ The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED, ++ and the waiting reader is never worken becuase as noted ++ above it is conditional on the futex being used. ++ ++ The solution is for the trylock thread to inspect ++ PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers. ++ ++ --- Analysis of pthread_rwlock_trywrlock() stall --- ++ ++ A write lock begins to execute, takes the write lock, ++ and then releases the lock... ++ ++ In pthread_rwlock_wrunlock(): ++ ++ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers); ++ ... ++ 549 while (!atomic_compare_exchange_weak_release ++ 550 (&rwlock->__data.__readers, &r, ++ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED) ++ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 ++ 553 : PTHREAD_RWLOCK_WRPHASE)))) ++ 554 { ++ ... ++ 556 } ++ ++ ... leaving it in the write phase with zero readers ++ (the case where we leave the write phase in place ++ during a write unlock). ++ ++ A write trylock begins to execute. ++ ++ In __pthread_rwlock_trywrlock: ++ ++ 40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0) ++ 41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0) ++ 42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0)))) ++ 43 { ++ ++ The lock is not locked. ++ ++ There are no readers. ++ ++ 45 if (atomic_compare_exchange_weak_acquire ( ++ 46 &rwlock->__data.__readers, &r, ++ 47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED)) ++ ++ We atomically install the write phase and we take the ++ exclusive write lock. ++ ++ 48 { ++ 49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1); ++ ++ We get this far. ++ ++ A reader lock begins to execute. ++ ++ In pthread_rwlock_rdlock: ++ ++ 437 for (;;) ++ 438 { ++ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) ++ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ 441 { ++ 442 int private = __pthread_rwlock_get_private (rwlock); ++ 443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) ++ 444 && (!atomic_compare_exchange_weak_relaxed ++ 445 (&rwlock->__data.__wrphase_futex, ++ 446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))) ++ 447 continue; ++ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, ++ 449 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ 450 abstime, private); ++ ++ We are in a write phase, so the while() on line 439 is true. ++ ++ The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set ++ since this is the first reader to lock. ++ ++ The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED ++ on the expectation that this reader will be woken during ++ the handoff. ++ ++ Back in pthread_rwlock_trywrlock: ++ ++ 50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); ++ 51 atomic_store_relaxed (&rwlock->__data.__cur_writer, ++ 52 THREAD_GETMEM (THREAD_SELF, tid)); ++ 53 return 0; ++ 54 } ++ ... ++ 57 } ++ ++ We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED, ++ and so in the unlock we will not awaken the waiting reader. ++ ++ The solution to this is to realize that if we did not start the write ++ phase we need not write 1 or any other value to __wrphase_futex. ++ This ensures that any readers (which saw __wrphase_futex != 0) can ++ set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to ++ wake them. ++ ++ If we installed the write phase then all other readers are looping ++ here: ++ ++ In __pthread_rwlock_rdlock_full: ++ ++ 437 for (;;) ++ 438 { ++ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) ++ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ 441 { ++ ... ++ 508 } ++ ++ waiting for the write phase to be installed or removed before they ++ can begin waiting on __wrphase_futex (part of the algorithm), or ++ taking a concurrent read lock, and thus we can safely write 1 to ++ __wrphase_futex. ++ ++ If we did not install the write phase then the readers may already ++ be waiting on the futex, the original writer wrote 1 to __wrphase_futex ++ as part of starting the write phase, and we cannot also write 1 ++ without loosing the PTHREAD_RWLOCK_FUTEX_USED bit. ++ ++ --- ++ ++ Summary for the pthread_rwlock_tryrdlock() stall: ++ ++ The stall is caused by pthread_rwlock_tryrdlock failing to check ++ that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex ++ and then waking the futex. ++ ++ The fix for bug 23844 ensures that waiters on __wrphase_futex are ++ correctly woken. Before the fix the test stalls as readers can ++ wait forever on __wrphase_futex. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* We need only one lock to reproduce the issue. We will need multiple ++ threads to get the exact case where we have a read, try, and unlock ++ all interleaving to produce the case where the readers are waiting ++ and the try fails to wake them. */ ++pthread_rwlock_t onelock; ++ ++/* The number of threads is arbitrary but empirically chosen to have ++ enough threads that we see the condition where waiting readers are ++ not woken by a successful tryrdlock. */ ++#define NTHREADS 32 ++ ++_Atomic int do_exit; ++ ++void * ++run_loop (void *arg) ++{ ++ int i = 0, ret; ++ while (!do_exit) ++ { ++ /* Arbitrarily choose if we are the writer or reader. Choose a ++ high enough ratio of readers to writers to make it likely ++ that readers block (and eventually are susceptable to ++ stalling). ++ ++ If we are a writer, take the write lock, and then unlock. ++ If we are a reader, try the lock, then lock, then unlock. */ ++ if ((i % 8) != 0) ++ xpthread_rwlock_wrlock (&onelock); ++ else ++ { ++ if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0) ++ { ++ if (ret == EBUSY) ++ xpthread_rwlock_rdlock (&onelock); ++ else ++ exit (EXIT_FAILURE); ++ } ++ } ++ /* Thread does some work and then unlocks. */ ++ xpthread_rwlock_unlock (&onelock); ++ i++; ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ int i; ++ pthread_t tids[NTHREADS]; ++ xpthread_rwlock_init (&onelock, NULL); ++ for (i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Run for some amount of time. Empirically speaking exercising ++ the stall via pthread_rwlock_tryrdlock is much harder, and on ++ a 3.5GHz 4 core x86_64 VM system it takes somewhere around ++ 20-200s to stall, approaching 100% stall past 200s. We can't ++ wait that long for a regression test so we just test for 20s, ++ and expect the stall to happen with a 5-10% chance (enough for ++ developers to see). */ ++ sleep (20); ++ /* Then exit. */ ++ printf ("INFO: Exiting...\n"); ++ do_exit = 1; ++ /* If any readers stalled then we will timeout waiting for them. */ ++ for (i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("INFO: Done.\n"); ++ xpthread_rwlock_destroy (&onelock); ++ printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n"); ++ return 0; ++} ++ ++#define TIMEOUT 30 ++#include +diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c +new file mode 100644 +index 0000000000..14d27cbcbc +--- /dev/null ++++ b/nptl/tst-rwlock-trywrlock-stall.c +@@ -0,0 +1,108 @@ ++/* Bug 23844: Test for pthread_rwlock_trywrlock stalls. ++ 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 ++ . */ ++ ++/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c. ++ ++ Summary for the pthread_rwlock_trywrlock() stall: ++ ++ The stall is caused by pthread_rwlock_trywrlock setting ++ __wrphase_futex futex to 1 and loosing the ++ PTHREAD_RWLOCK_FUTEX_USED bit. ++ ++ The fix for bug 23844 ensures that waiters on __wrphase_futex are ++ correctly woken. Before the fix the test stalls as readers can ++ wait forever on __wrphase_futex. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* We need only one lock to reproduce the issue. We will need multiple ++ threads to get the exact case where we have a read, try, and unlock ++ all interleaving to produce the case where the readers are waiting ++ and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a ++ subsequent unlock fails to wake them. */ ++pthread_rwlock_t onelock; ++ ++/* The number of threads is arbitrary but empirically chosen to have ++ enough threads that we see the condition where waiting readers are ++ not woken by a successful unlock. */ ++#define NTHREADS 32 ++ ++_Atomic int do_exit; ++ ++void * ++run_loop (void *arg) ++{ ++ int i = 0, ret; ++ while (!do_exit) ++ { ++ /* Arbitrarily choose if we are the writer or reader. Choose a ++ high enough ratio of readers to writers to make it likely ++ that readers block (and eventually are susceptable to ++ stalling). ++ ++ If we are a writer, take the write lock, and then unlock. ++ If we are a reader, try the lock, then lock, then unlock. */ ++ if ((i % 8) != 0) ++ { ++ if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0) ++ { ++ if (ret == EBUSY) ++ xpthread_rwlock_wrlock (&onelock); ++ else ++ exit (EXIT_FAILURE); ++ } ++ } ++ else ++ xpthread_rwlock_rdlock (&onelock); ++ /* Thread does some work and then unlocks. */ ++ xpthread_rwlock_unlock (&onelock); ++ i++; ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ int i; ++ pthread_t tids[NTHREADS]; ++ xpthread_rwlock_init (&onelock, NULL); ++ for (i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Run for some amount of time. The pthread_rwlock_tryrwlock stall ++ is very easy to trigger and happens in seconds under the test ++ conditions. */ ++ sleep (10); ++ /* Then exit. */ ++ printf ("INFO: Exiting...\n"); ++ do_exit = 1; ++ /* If any readers stalled then we will timeout waiting for them. */ ++ for (i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("INFO: Done.\n"); ++ xpthread_rwlock_destroy (&onelock); ++ printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n"); ++ return 0; ++} ++ ++#include +diff --git a/support/Makefile b/support/Makefile +index 432cf2fe6c..c15b93647c 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -129,6 +129,7 @@ libsupport-routines = \ + xpthread_mutexattr_settype \ + xpthread_once \ + xpthread_rwlock_init \ ++ xpthread_rwlock_destroy \ + xpthread_rwlock_rdlock \ + xpthread_rwlock_unlock \ + xpthread_rwlock_wrlock \ +diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c +new file mode 100644 +index 0000000000..6d6e953569 +--- /dev/null ++++ b/support/xpthread_rwlock_destroy.c +@@ -0,0 +1,26 @@ ++/* pthread_rwlock_destroy with error checking. ++ 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 ++ . */ ++ ++#include ++ ++void ++xpthread_rwlock_destroy (pthread_rwlock_t *rwlock) ++{ ++ xpthread_check_return ("pthread_rwlock_destroy", ++ pthread_rwlock_destroy (rwlock)); ++} +diff --git a/support/xthread.h b/support/xthread.h +index 47c23235f3..9fe1f68b3b 100644 +--- a/support/xthread.h ++++ b/support/xthread.h +@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref); + void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock); + void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock); + void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock); ++void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock); + + __END_DECLS + + diff --git a/srcpkgs/glibc/patches/glibc-upstream-02.patch b/srcpkgs/glibc/patches/glibc-upstream-02.patch new file mode 100644 index 00000000000..28231b3b005 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-02.patch @@ -0,0 +1,248 @@ +From 726a78867b3144e9b9da10197bcf59bde3d8b2a4 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 4 Feb 2019 08:55:52 -0800 +Subject: [PATCH 02] x86-64 memcmp: Use unsigned Jcc instructions on size + [BZ #24155] + +Since the size argument is unsigned. we should use unsigned Jcc +instructions, instead of signed, to check size. + +Tested on x86-64 and x32, with and without --disable-multi-arch. + + [BZ #24155] + CVE-2019-7309 + * NEWS: Updated for CVE-2019-7309. + * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the + upper 32 bits of RDX register for x32. Use unsigned Jcc + instructions, instead of signed. + * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2. + * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test. + +(cherry picked from commit 3f635fb43389b54f682fc9ed2acc0b2aaf4a923d) +--- + ChangeLog | 11 ++++ + NEWS | 17 +++++ + sysdeps/x86_64/memcmp.S | 20 +++--- + sysdeps/x86_64/x32/Makefile | 3 +- + sysdeps/x86_64/x32/tst-size_t-memcmp-2.c | 79 ++++++++++++++++++++++++ + 5 files changed, 121 insertions(+), 9 deletions(-) + create mode 100644 sysdeps/x86_64/x32/tst-size_t-memcmp-2.c + +diff --git a/ChangeLog b/ChangeLog +index adb4e719a6..e0969afd80 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,14 @@ ++2019-02-04 H.J. Lu ++ ++ [BZ #24155] ++ CVE-2019-7309 ++ * NEWS: Updated for CVE-2019-7309. ++ * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the ++ upper 32 bits of RDX register for x32. Use unsigned Jcc ++ instructions, instead of signed. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2. ++ * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test. ++ + 2019-01-31 Carlos O'Donell + Torvald Riegel + Rik Prohaska +diff --git a/NEWS b/NEWS +index 912a9bdc0f..1751ed118a 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,23 @@ See the end for copying conditions. + Please send GNU C library bug reports via + using `glibc' in the "product" field. + ++Version 2.29.1 ++ ++The following bugs are resolved with this release: ++ ++ [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) ++ ++Security related changes: ++ ++ CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check ++ size. For x86-64, memcmp on an object size larger than SSIZE_MAX ++ has undefined behavior. On x32, the size_t argument may be passed ++ in the lower 32 bits of the 64-bit RDX register with non-zero upper ++ 32 bits. When it happened with the sign bit of RDX register set, ++ memcmp gave the wrong result since it treated the size argument as ++ zero. Reported by H.J. Lu. ++ ++ + Version 2.29 + + Major new features: +diff --git a/sysdeps/x86_64/memcmp.S b/sysdeps/x86_64/memcmp.S +index 1fc487caa5..1322bb3b92 100644 +--- a/sysdeps/x86_64/memcmp.S ++++ b/sysdeps/x86_64/memcmp.S +@@ -21,14 +21,18 @@ + + .text + ENTRY (memcmp) +- test %rdx, %rdx ++#ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++#endif ++ test %RDX_LP, %RDX_LP + jz L(finz) + cmpq $1, %rdx +- jle L(finr1b) ++ jbe L(finr1b) + subq %rdi, %rsi + movq %rdx, %r10 + cmpq $32, %r10 +- jge L(gt32) ++ jae L(gt32) + /* Handle small chunks and last block of less than 32 bytes. */ + L(small): + testq $1, %r10 +@@ -156,7 +160,7 @@ L(A32): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + /* Pre-unroll to be ready for unrolled 64B loop. */ + testq $32, %rdi + jz L(A64) +@@ -178,7 +182,7 @@ L(A64): + movq %r11, %r10 + andq $-64, %r10 + cmpq %r10, %rdi +- jge L(mt32) ++ jae L(mt32) + + L(A64main): + movdqu (%rdi,%rsi), %xmm0 +@@ -216,7 +220,7 @@ L(mt32): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + + L(A32main): + movdqu (%rdi,%rsi), %xmm0 +@@ -254,7 +258,7 @@ L(ATR): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + testq $16, %rdi + jz L(ATR32) + +@@ -325,7 +329,7 @@ L(ATR64main): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + + L(ATR32res): + movdqa (%rdi,%rsi), %xmm0 +diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile +index 1557724b0c..8748956563 100644 +--- a/sysdeps/x86_64/x32/Makefile ++++ b/sysdeps/x86_64/x32/Makefile +@@ -8,7 +8,8 @@ endif + ifeq ($(subdir),string) + tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \ + tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \ +- tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen ++ tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \ ++ tst-size_t-memcmp-2 + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c +new file mode 100644 +index 0000000000..d8ae1a0813 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c +@@ -0,0 +1,79 @@ ++/* Test memcmp with size_t in the lower 32 bits of 64-bit register. ++ 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 ++ . */ ++ ++#define TEST_MAIN ++#ifdef WIDE ++# define TEST_NAME "wmemcmp" ++#else ++# define TEST_NAME "memcmp" ++#endif ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++# include ++ ++# define MEMCMP wmemcmp ++# define CHAR wchar_t ++#else ++# define MEMCMP memcmp ++# define CHAR char ++#endif ++ ++IMPL (MEMCMP, 1) ++ ++typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); ++ ++static int ++__attribute__ ((noinline, noclone)) ++do_memcmp (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ memcpy (buf1, buf2, page_size); ++ ++ CHAR *p = (CHAR *) buf1; ++ p[page_size / sizeof (CHAR) - 1] = (CHAR) 1; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ int res = do_memcmp (dest, src); ++ if (res >= 0) ++ { ++ error (0, 0, "Wrong result in function %s: %i >= 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include + diff --git a/srcpkgs/glibc/patches/glibc-upstream-03.patch b/srcpkgs/glibc/patches/glibc-upstream-03.patch new file mode 100644 index 00000000000..1568201a0a5 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-03.patch @@ -0,0 +1,119 @@ +From 2de15ac95713a238dc258eb8977ecdfca811fc19 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 5 Feb 2019 13:49:02 +0100 +Subject: [PATCH 03] arm: Use "nr" constraint for Systemtap probes [BZ + #24164] + +With the default "nor" constraint, current GCC will use the "o" +constraint for constants, after emitting the constant to memory. That +results in unparseable Systemtap probe notes such as "-4@.L1052". +Removing the "o" alternative and using "nr" instead avoids this. + +(cherry picked from commit f1ac7455831546e5dca0ed98fe8af2686fae7ce6) +--- + ChangeLog | 11 +++++++++++ + NEWS | 1 + + include/stap-probe.h | 1 + + sysdeps/arm/stap-probe-machine.h | 22 ++++++++++++++++++++++ + sysdeps/generic/stap-probe-machine.h | 19 +++++++++++++++++++ + 5 files changed, 54 insertions(+) + create mode 100644 sysdeps/arm/stap-probe-machine.h + create mode 100644 sysdeps/generic/stap-probe-machine.h + +diff --git a/ChangeLog b/ChangeLog +index e0969afd80..9517ff9e82 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,14 @@ ++2019-02-05 Florian Weimer ++ ++ [BZ #24164] ++ arm: Use "nr" constraint for Systemtap probes, to avoid the ++ compiler using memory operands for constants, due to the "o" ++ alternative in the default "nor" constraint. ++ * include/stap-probe.h [USE_STAP_PROBE]: Include ++ ++ * sysdeps/generic/stap-probe-machine.h: New file. ++ * sysdeps/arm/stap-probe-machine.h: Likewise. ++ + 2019-02-04 H.J. Lu + + [BZ #24155] +diff --git a/NEWS b/NEWS +index 1751ed118a..1f0fc4b3cb 100644 +--- a/NEWS ++++ b/NEWS +@@ -10,6 +10,7 @@ Version 2.29.1 + The following bugs are resolved with this release: + + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) ++ [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + + Security related changes: + +diff --git a/include/stap-probe.h b/include/stap-probe.h +index c53dd86592..8c26292edd 100644 +--- a/include/stap-probe.h ++++ b/include/stap-probe.h +@@ -21,6 +21,7 @@ + + #ifdef USE_STAP_PROBE + ++# include + # include + + /* Our code uses one macro LIBC_PROBE (name, n, arg1, ..., argn). +diff --git a/sysdeps/arm/stap-probe-machine.h b/sysdeps/arm/stap-probe-machine.h +new file mode 100644 +index 0000000000..d27ca22040 +--- /dev/null ++++ b/sysdeps/arm/stap-probe-machine.h +@@ -0,0 +1,22 @@ ++/* Macros for customizing Systemtap . Arm version. ++ 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 ++ . */ ++ ++/* The default "nor" constraint produces unparseable memory references ++ for constants. Omit the problematic "o" constraint. See bug 24164 ++ and GCC PR 89146. */ ++#define STAP_SDT_ARG_CONSTRAINT nr +diff --git a/sysdeps/generic/stap-probe-machine.h b/sysdeps/generic/stap-probe-machine.h +new file mode 100644 +index 0000000000..2e5790c3b2 +--- /dev/null ++++ b/sysdeps/generic/stap-probe-machine.h +@@ -0,0 +1,19 @@ ++/* Macros for customizing Systemtap . Generic version. ++ 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 ++ . */ ++ ++/* By default, there are no customizations. */ + diff --git a/srcpkgs/glibc/patches/glibc-upstream-04.patch b/srcpkgs/glibc/patches/glibc-upstream-04.patch new file mode 100644 index 00000000000..43a39b90f27 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-04.patch @@ -0,0 +1,221 @@ +From 44113a8ba24af23d7bbb174f9087a6b83a76289a Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Thu, 7 Feb 2019 15:18:36 +0100 +Subject: [PATCH 04] Add compiler barriers around modifications of the + robust mutex list for pthread_mutex_trylock. [BZ #24180] + +While debugging a kernel warning, Thomas Gleixner, Sebastian Sewior and +Heiko Carstens found a bug in pthread_mutex_trylock due to misordered +instructions: +140: a5 1b 00 01 oill %r1,1 +144: e5 48 a0 f0 00 00 mvghi 240(%r10),0 <--- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); +14a: e3 10 a0 e0 00 24 stg %r1,224(%r10) <--- last THREAD_SETMEM of ENQUEUE_MUTEX_PI + +vs (with compiler barriers): +140: a5 1b 00 01 oill %r1,1 +144: e3 10 a0 e0 00 24 stg %r1,224(%r10) +14a: e5 48 a0 f0 00 00 mvghi 240(%r10),0 + +Please have a look at the discussion: +"Re: WARN_ON_ONCE(!new_owner) within wake_futex_pi() triggerede" +(https://lore.kernel.org/lkml/20190202112006.GB3381@osiris/) + +This patch is introducing the same compiler barriers and comments +for pthread_mutex_trylock as introduced for pthread_mutex_lock and +pthread_mutex_timedlock by commit 8f9450a0b7a9e78267e8ae1ab1000ebca08e473e +"Add compiler barriers around modifications of the robust mutex list." + +ChangeLog: + + [BZ #24180] + * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): + Add compiler barriers and comments. + +(cherry picked from commit 823624bdc47f1f80109c9c52dee7939b9386d708) +--- + ChangeLog | 6 ++++ + nptl/pthread_mutex_trylock.c | 57 +++++++++++++++++++++++++++++++++--- + 2 files changed, 59 insertions(+), 4 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 9517ff9e82..7a8895bcc6 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2019-02-07 Stefan Liebler ++ ++ [BZ #24180] ++ * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): ++ Add compiler barriers and comments. ++ + 2019-02-05 Florian Weimer + + [BZ #24164] +diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c +index 8fe43b8f0f..bf2869eca2 100644 +--- a/nptl/pthread_mutex_trylock.c ++++ b/nptl/pthread_mutex_trylock.c +@@ -94,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); ++ /* We need to set op_pending before starting the operation. Also ++ see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); + + oldval = mutex->__data.__lock; + do +@@ -119,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + ++ /* We must not enqueue the mutex before we have acquired it. ++ Also see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); + ENQUEUE_MUTEX (mutex); ++ /* We need to clear op_pending after we enqueue the mutex. */ ++ __asm ("" ::: "memory"); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exist here. If we fall +@@ -135,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { ++ /* We do not need to ensure ordering wrt another memory ++ access. Also see comments at ENQUEUE_MUTEX. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; +@@ -142,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { ++ /* We do not need to ensure ordering wrt another memory ++ access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + +@@ -160,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + id, 0); + if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0) + { ++ /* We haven't acquired the lock as it is already acquired by ++ another owner. We do not need to ensure ordering wrt another ++ memory access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; +@@ -173,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + if (oldval == id) + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); ++ /* FIXME This violates the mutex destruction requirements. See ++ __pthread_mutex_unlock_full. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + ++ /* We must not enqueue the mutex before we have acquired it. ++ Also see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); + ENQUEUE_MUTEX (mutex); ++ /* We need to clear op_pending after we enqueue the mutex. */ ++ __asm ("" ::: "memory"); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + mutex->__data.__owner = id; +@@ -211,10 +233,15 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + } + + if (robust) +- /* Note: robust PI futexes are signaled by setting bit 0. */ +- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, +- (void *) (((uintptr_t) &mutex->__data.__list.__next) +- | 1)); ++ { ++ /* Note: robust PI futexes are signaled by setting bit 0. */ ++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, ++ (void *) (((uintptr_t) &mutex->__data.__list.__next) ++ | 1)); ++ /* We need to set op_pending before starting the operation. Also ++ see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); ++ } + + oldval = mutex->__data.__lock; + +@@ -223,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { ++ /* We do not need to ensure ordering wrt another memory ++ access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { ++ /* We do not need to ensure ordering wrt another memory ++ access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ +@@ -250,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + { + if ((oldval & FUTEX_OWNER_DIED) == 0) + { ++ /* We haven't acquired the lock as it is already acquired by ++ another owner. We do not need to ensure ordering wrt another ++ memory access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; +@@ -270,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) + { ++ /* The kernel has not yet finished the mutex owner death. ++ We do not need to ensure ordering wrt another memory ++ access. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; +@@ -287,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + ++ /* We must not enqueue the mutex before we have acquired it. ++ Also see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); + ENQUEUE_MUTEX (mutex); ++ /* We need to clear op_pending after we enqueue the mutex. */ ++ __asm ("" ::: "memory"); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall +@@ -310,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + ++ /* To the kernel, this will be visible after the kernel has ++ acquired the mutex in the syscall. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (robust) + { ++ /* We must not enqueue the mutex before we have acquired it. ++ Also see comments at ENQUEUE_MUTEX. */ ++ __asm ("" ::: "memory"); + ENQUEUE_MUTEX_PI (mutex); ++ /* We need to clear op_pending after we enqueue the mutex. */ ++ __asm ("" ::: "memory"); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + + diff --git a/srcpkgs/glibc/patches/glibc-upstream-05.patch b/srcpkgs/glibc/patches/glibc-upstream-05.patch new file mode 100644 index 00000000000..87b4efedbeb --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-05.patch @@ -0,0 +1,157 @@ +From c096b008d2671028c21ac8cf01f18a2083e73c44 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 8 Feb 2019 12:54:41 +0100 +Subject: [PATCH 05] nptl: Avoid fork handler lock for async-signal-safe + fork [BZ #24161] + +Commit 27761a1042daf01987e7d79636d0c41511c6df3c ("Refactor atfork +handlers") introduced a lock, atfork_lock, around fork handler list +accesses. It turns out that this lock occasionally results in +self-deadlocks in malloc/tst-mallocfork2: + +(gdb) bt +#0 __lll_lock_wait_private () + at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:63 +#1 0x00007f160c6f927a in __run_fork_handlers (who=(unknown: 209394016), + who@entry=atfork_run_prepare) at register-atfork.c:116 +#2 0x00007f160c6b7897 in __libc_fork () at ../sysdeps/nptl/fork.c:58 +#3 0x00000000004027d6 in sigusr1_handler (signo=) + at tst-mallocfork2.c:80 +#4 sigusr1_handler (signo=) at tst-mallocfork2.c:64 +#5 +#6 0x00007f160c6f92e4 in __run_fork_handlers (who=who@entry=atfork_run_parent) + at register-atfork.c:136 +#7 0x00007f160c6b79a2 in __libc_fork () at ../sysdeps/nptl/fork.c:152 +#8 0x0000000000402567 in do_test () at tst-mallocfork2.c:156 +#9 0x0000000000402dd2 in support_test_main (argc=1, argv=0x7ffc81ef1ab0, + config=config@entry=0x7ffc81ef1970) at support_test_main.c:350 +#10 0x0000000000402362 in main (argc=, argv=) + at ../support/test-driver.c:168 + +If no locking happens in the single-threaded case (where fork is +expected to be async-signal-safe), this deadlock is avoided. +(pthread_atfork is not required to be async-signal-safe, so a fork +call from a signal handler interrupting pthread_atfork is not +a problem.) + +(cherry picked from commit 669ff911e2571f74a2668493e326ac9a505776bd) +--- + ChangeLog | 10 ++++++++++ + NEWS | 1 + + nptl/register-atfork.c | 8 +++++--- + sysdeps/nptl/fork.c | 6 +++--- + sysdeps/nptl/fork.h | 8 +++++--- + 5 files changed, 24 insertions(+), 9 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 7a8895bcc6..d363be4620 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,13 @@ ++2019-02-08 Florian Weimer ++ ++ [BZ #24161] ++ * sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads ++ argument. ++ * nptl/register-atfork.c (__run_fork_handlers): Only perform ++ locking if the new do_locking argument is true. ++ * sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to ++ __run_fork_handlers. ++ + 2019-02-07 Stefan Liebler + + [BZ #24180] +diff --git a/NEWS b/NEWS +index 1f0fc4b3cb..dbcdd48502 100644 +--- a/NEWS ++++ b/NEWS +@@ -11,6 +11,7 @@ The following bugs are resolved with this release: + + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm ++ [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 + + Security related changes: + +diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c +index bc797b761a..80a1becb5f 100644 +--- a/nptl/register-atfork.c ++++ b/nptl/register-atfork.c +@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle) + } + + void +-__run_fork_handlers (enum __run_fork_handler_type who) ++__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking) + { + struct fork_handler *runp; + + if (who == atfork_run_prepare) + { +- lll_lock (atfork_lock, LLL_PRIVATE); ++ if (do_locking) ++ lll_lock (atfork_lock, LLL_PRIVATE); + size_t sl = fork_handler_list_size (&fork_handlers); + for (size_t i = sl; i > 0; i--) + { +@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who) + else if (who == atfork_run_parent && runp->parent_handler) + runp->parent_handler (); + } +- lll_unlock (atfork_lock, LLL_PRIVATE); ++ if (do_locking) ++ lll_unlock (atfork_lock, LLL_PRIVATE); + } + } + +diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index bd68f18b45..14b69a6f89 100644 +--- a/sysdeps/nptl/fork.c ++++ b/sysdeps/nptl/fork.c +@@ -55,7 +55,7 @@ __libc_fork (void) + but our current fork implementation is not. */ + bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads); + +- __run_fork_handlers (atfork_run_prepare); ++ __run_fork_handlers (atfork_run_prepare, multiple_threads); + + /* If we are not running multiple threads, we do not have to + preserve lock state. If fork runs from a signal handler, only +@@ -134,7 +134,7 @@ __libc_fork (void) + __rtld_lock_initialize (GL(dl_load_lock)); + + /* Run the handlers registered for the child. */ +- __run_fork_handlers (atfork_run_child); ++ __run_fork_handlers (atfork_run_child, multiple_threads); + } + else + { +@@ -149,7 +149,7 @@ __libc_fork (void) + } + + /* Run the handlers registered for the parent. */ +- __run_fork_handlers (atfork_run_parent); ++ __run_fork_handlers (atfork_run_parent, multiple_threads); + } + + return pid; +diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h +index a1c3b26b68..99ed76034b 100644 +--- a/sysdeps/nptl/fork.h ++++ b/sysdeps/nptl/fork.h +@@ -52,9 +52,11 @@ enum __run_fork_handler_type + - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal + lock. + - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal +- lock. */ +-extern void __run_fork_handlers (enum __run_fork_handler_type who) +- attribute_hidden; ++ lock. ++ ++ Perform locking only if DO_LOCKING. */ ++extern void __run_fork_handlers (enum __run_fork_handler_type who, ++ _Bool do_locking) attribute_hidden; + + /* C library side function to register new fork handlers. */ + extern int __register_atfork (void (*__prepare) (void), + diff --git a/srcpkgs/glibc/patches/glibc-upstream-06.patch b/srcpkgs/glibc/patches/glibc-upstream-06.patch new file mode 100644 index 00000000000..fc0b41e5977 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-06.patch @@ -0,0 +1,86 @@ +From 067fc32968b601493f4b247a3ac00caeea3f3d61 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 15 Feb 2019 21:27:01 +0100 +Subject: [PATCH 06] nptl: Fix invalid Systemtap probe in pthread_join [BZ + #24211] + +After commit f1ac7455831546e5dca0ed98fe8af2686fae7ce6 ("arm: Use "nr" +constraint for Systemtap probes [BZ #24164]"), we load pd->result into +a register in the probe below: + + /* Free the TCB. */ + __free_tcb (pd); + } + else + pd->joinid = NULL; + + LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result); + +However, at this point, the thread descriptor has been freed. If the +thread stack does not fit into the thread stack cache, the memory will +have been unmapped, and the program will crash in the probe. + +(cherry picked from commit bc10e22c90e42613bd5dafb77b80a9ea1759dd1b) +--- + ChangeLog | 6 ++++++ + NEWS | 1 + + nptl/pthread_join_common.c | 5 +++-- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index d363be4620..a6a0ce19ed 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2019-02-15 Florian Weimer ++ ++ [BZ #24211] ++ * nptl/pthread_join_common.c (__pthread_timedjoin_ex): Do not read ++ pd->result after the thread descriptor has been freed. ++ + 2019-02-08 Florian Weimer + + [BZ #24161] +diff --git a/NEWS b/NEWS +index dbcdd48502..340e06d0f4 100644 +--- a/NEWS ++++ b/NEWS +@@ -12,6 +12,7 @@ The following bugs are resolved with this release: + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 ++ [24211] Use-after-free in Systemtap probe in pthread_join + + Security related changes: + +diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c +index ecb78ffba5..366feb376b 100644 +--- a/nptl/pthread_join_common.c ++++ b/nptl/pthread_join_common.c +@@ -86,6 +86,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return, + pthread_cleanup_pop (0); + } + ++ void *pd_result = pd->result; + if (__glibc_likely (result == 0)) + { + /* We mark the thread as terminated and as joined. */ +@@ -93,7 +94,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return, + + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) +- *thread_return = pd->result; ++ *thread_return = pd_result; + + /* Free the TCB. */ + __free_tcb (pd); +@@ -101,7 +102,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return, + else + pd->joinid = NULL; + +- LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result); ++ LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd_result); + + return result; + } + diff --git a/srcpkgs/glibc/patches/glibc-upstream-07.patch b/srcpkgs/glibc/patches/glibc-upstream-07.patch new file mode 100644 index 00000000000..e7467b8c8bf --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-07.patch @@ -0,0 +1,161 @@ +From bc6f839fb4066be83272c735e662850af2595777 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 13 Mar 2019 10:45:35 +0100 +Subject: [PATCH 07] Fix output of LD_SHOW_AUXV=1. + +Starting with commit 1616d034b61622836d3a36af53dcfca7624c844e +the output was corrupted on some platforms as _dl_procinfo +was called for every auxv entry and on some architectures like s390 +all entries were represented as "AT_HWCAP". + +This patch is removing the condition and let _dl_procinfo decide if +an entry is printed in a platform specific or generic way. +This patch also adjusts all _dl_procinfo implementations which assumed +that they are only called for AT_HWCAP or AT_HWCAP2. They are now just +returning a non-zero-value for entries which are not handled platform +specifc. + +ChangeLog: + + * elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always + call _dl_procinfo. + * sysdeps/unix/sysv/linux/s390/dl-procinfo.h (_dl_procinfo): + Ignore types other than AT_HWCAP. + * sysdeps/sparc/dl-procinfo.h (_dl_procinfo): Likewise. + * sysdeps/unix/sysv/linux/i386/dl-procinfo.h (_dl_procinfo): + Likewise. + * sysdeps/powerpc/dl-procinfo.h (_dl_procinfo): Adjust comment + in the case of falling back to generic output mechanism. + * sysdeps/unix/sysv/linux/arm/dl-procinfo.h (_dl_procinfo): + Likewise. + +(cherry picked from commit 7c6513082b787a7d36ab7d75720b48f8a216089c) + +Conflicts: + ChangeLog +--- + ChangeLog | 14 ++++++++++++++ + elf/dl-sysdep.c | 11 +++-------- + sysdeps/powerpc/dl-procinfo.h | 2 +- + sysdeps/sparc/dl-procinfo.h | 4 ++-- + sysdeps/unix/sysv/linux/arm/dl-procinfo.h | 2 +- + sysdeps/unix/sysv/linux/i386/dl-procinfo.h | 4 ++-- + sysdeps/unix/sysv/linux/s390/dl-procinfo.h | 4 ++-- + 7 files changed, 25 insertions(+), 16 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index a6a0ce19ed..90558e434c 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,17 @@ ++2019-03-13 Stefan Liebler ++ ++ * elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always ++ call _dl_procinfo. ++ * sysdeps/unix/sysv/linux/s390/dl-procinfo.h (_dl_procinfo): ++ Ignore types other than AT_HWCAP. ++ * sysdeps/sparc/dl-procinfo.h (_dl_procinfo): Likewise. ++ * sysdeps/unix/sysv/linux/i386/dl-procinfo.h (_dl_procinfo): ++ Likewise. ++ * sysdeps/powerpc/dl-procinfo.h (_dl_procinfo): Adjust comment ++ in the case of falling back to generic output mechanism. ++ * sysdeps/unix/sysv/linux/arm/dl-procinfo.h (_dl_procinfo): ++ Likewise. ++ + 2019-02-15 Florian Weimer + + [BZ #24211] +diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c +index 5f6c679a3f..5d19b100b2 100644 +--- a/elf/dl-sysdep.c ++++ b/elf/dl-sysdep.c +@@ -328,14 +328,9 @@ _dl_show_auxv (void) + assert (AT_NULL == 0); + assert (AT_IGNORE == 1); + +- if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2 +- || AT_L1I_CACHEGEOMETRY || AT_L1D_CACHEGEOMETRY +- || AT_L2_CACHEGEOMETRY || AT_L3_CACHEGEOMETRY) +- { +- /* These are handled in a special way per platform. */ +- if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0) +- continue; +- } ++ /* Some entries are handled in a special way per platform. */ ++ if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0) ++ continue; + + if (idx < sizeof (auxvars) / sizeof (auxvars[0]) + && auxvars[idx].form != unknown) +diff --git a/sysdeps/powerpc/dl-procinfo.h b/sysdeps/powerpc/dl-procinfo.h +index f542f7318f..dfc3b33a72 100644 +--- a/sysdeps/powerpc/dl-procinfo.h ++++ b/sysdeps/powerpc/dl-procinfo.h +@@ -225,7 +225,7 @@ _dl_procinfo (unsigned int type, unsigned long int word) + break; + } + default: +- /* This should not happen. */ ++ /* Fallback to generic output mechanism. */ + return -1; + } + _dl_printf ("\n"); +diff --git a/sysdeps/sparc/dl-procinfo.h b/sysdeps/sparc/dl-procinfo.h +index 282b8c5117..64ee267fc7 100644 +--- a/sysdeps/sparc/dl-procinfo.h ++++ b/sysdeps/sparc/dl-procinfo.h +@@ -31,8 +31,8 @@ _dl_procinfo (unsigned int type, unsigned long int word) + { + int i; + +- /* Fallback to unknown output mechanism. */ +- if (type == AT_HWCAP2) ++ /* Fallback to generic output mechanism. */ ++ if (type != AT_HWCAP) + return -1; + + _dl_printf ("AT_HWCAP: "); +diff --git a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h +index 66c00297b7..05c62c8687 100644 +--- a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h ++++ b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h +@@ -67,7 +67,7 @@ _dl_procinfo (unsigned int type, unsigned long int word) + break; + } + default: +- /* This should not happen. */ ++ /* Fallback to generic output mechanism. */ + return -1; + } + _dl_printf ("\n"); +diff --git a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h +index 22b43431bc..0585cdaa9c 100644 +--- a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h ++++ b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h +@@ -30,8 +30,8 @@ _dl_procinfo (unsigned int type, unsigned long int word) + in the kernel sources. */ + int i; + +- /* Fallback to unknown output mechanism. */ +- if (type == AT_HWCAP2) ++ /* Fallback to generic output mechanism. */ ++ if (type != AT_HWCAP) + return -1; + + _dl_printf ("AT_HWCAP: "); +diff --git a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h +index 19329a335b..d67fde368f 100644 +--- a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h ++++ b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h +@@ -32,8 +32,8 @@ _dl_procinfo (unsigned int type, unsigned long int word) + in the kernel sources. */ + int i; + +- /* Fallback to unknown output mechanism. */ +- if (type == AT_HWCAP2) ++ /* Fallback to generic output mechanism. */ ++ if (type != AT_HWCAP) + return -1; + + _dl_printf ("AT_HWCAP: "); + diff --git a/srcpkgs/glibc/patches/glibc-upstream-08.patch b/srcpkgs/glibc/patches/glibc-upstream-08.patch new file mode 100644 index 00000000000..a03b81a83b7 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-08.patch @@ -0,0 +1,50 @@ +From 4d0b1b0f61bfba034e9e76a1d76acc59c975238f Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Mon, 21 Jan 2019 11:08:13 -0800 +Subject: [PATCH 08] regex: fix read overrun [BZ #24114] + +Problem found by AddressSanitizer, reported by Hongxu Chen in: +https://debbugs.gnu.org/34140 +* posix/regexec.c (proceed_next_node): +Do not read past end of input buffer. + +(cherry picked from commit 583dd860d5b833037175247230a328f0050dbfe9) +--- + ChangeLog | 8 ++++++++ + posix/regexec.c | 6 ++++-- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 90558e434c..fb88626efe 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,11 @@ ++2019-01-31 Paul Eggert ++ ++ regex: fix read overrun [BZ #24114] ++ Problem found by AddressSanitizer, reported by Hongxu Chen in: ++ https://debbugs.gnu.org/34140 ++ * posix/regexec.c (proceed_next_node): ++ Do not read past end of input buffer. ++ + 2019-03-13 Stefan Liebler + + * elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always +diff --git a/posix/regexec.c b/posix/regexec.c +index 91d5a797b8..084b1222d9 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -1293,8 +1293,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); +- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, +- naccepted) != 0) ++ if (mctx->input.valid_len - *pidx < naccepted ++ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, ++ naccepted) ++ != 0)) + return -1; + } + } + diff --git a/srcpkgs/glibc/patches/glibc-upstream-09.patch b/srcpkgs/glibc/patches/glibc-upstream-09.patch new file mode 100644 index 00000000000..117658e0b8a --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-09.patch @@ -0,0 +1,38 @@ +From 10dd17da710fd32aaf1f2187544d80064b8c4ee0 Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Sat, 16 Mar 2019 22:59:56 +0100 +Subject: [PATCH 09] Record CVE-2019-9169 in NEWS and ChangeLog [BZ #24114] + +(cherry picked from commit b626c5aa5d0673a9caa48fb79fba8bda237e6fa8) +--- + ChangeLog | 1 + + NEWS | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/ChangeLog b/ChangeLog +index fb88626efe..80413dd560 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,5 +1,6 @@ + 2019-01-31 Paul Eggert + ++ CVE-2019-9169 + regex: fix read overrun [BZ #24114] + Problem found by AddressSanitizer, reported by Hongxu Chen in: + https://debbugs.gnu.org/34140 +diff --git a/NEWS b/NEWS +index 340e06d0f4..271bf7a2cd 100644 +--- a/NEWS ++++ b/NEWS +@@ -24,6 +24,10 @@ Security related changes: + memcmp gave the wrong result since it treated the size argument as + zero. Reported by H.J. Lu. + ++ CVE-2019-9169: Attempted case-insensitive regular-expression match ++ via proceed_next_node in posix/regexec.c leads to heap-based buffer ++ over-read. Reported by Hongxu Chen. ++ + + Version 2.29 + + diff --git a/srcpkgs/glibc/patches/glibc-upstream-10.patch b/srcpkgs/glibc/patches/glibc-upstream-10.patch new file mode 100644 index 00000000000..cd53db26b94 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-10.patch @@ -0,0 +1,51 @@ +From 6eb48fe80cb6dd3ef536e86d005976d1c22b170e Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Thu, 21 Mar 2019 09:14:26 +0100 +Subject: [PATCH 10] S390: Mark vx and vxe as important hwcap. + +This patch adds vx and vxe as important hwcaps +which allows one to provide shared libraries +tuned for platforms with non-vx/-vxe, vx or vxe. + +ChangeLog: + + * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT): + Add HWCAP_S390_VX and HWCAP_S390_VXE. + +(cherry picked from commit 61f5e9470fb397a4c334938ac5a667427d9047df) + +Conflicts: + ChangeLog +--- + ChangeLog | 5 +++++ + sysdeps/s390/dl-procinfo.h | 3 ++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/ChangeLog b/ChangeLog +index 80413dd560..7111aeb149 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2019-03-21 Stefan Liebler ++ ++ * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT): ++ Add HWCAP_S390_VX and HWCAP_S390_VXE. ++ + 2019-01-31 Paul Eggert + + CVE-2019-9169 +diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +index b4b81fc70a..99697ae649 100644 +--- a/sysdeps/s390/dl-procinfo.h ++++ b/sysdeps/s390/dl-procinfo.h +@@ -57,7 +57,8 @@ enum + }; + + #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ +- | HWCAP_S390_EIMM | HWCAP_S390_DFP) ++ | HWCAP_S390_EIMM | HWCAP_S390_DFP \ ++ | HWCAP_S390_VX | HWCAP_S390_VXE) + + /* We cannot provide a general printing function. */ + #define _dl_procinfo(type, word) -1 + diff --git a/srcpkgs/glibc/patches/glibc-upstream-11.patch b/srcpkgs/glibc/patches/glibc-upstream-11.patch new file mode 100644 index 00000000000..2930fbbf361 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-11.patch @@ -0,0 +1,52 @@ +From e28ad442e73b00ae2047d89c8cc7f9b2a0de5436 Mon Sep 17 00:00:00 2001 +From: TAMUKI Shoichi +Date: Sat, 2 Mar 2019 21:00:28 +0900 +Subject: [PATCH 11] ja_JP: Change the offset for Taisho gan-nen from 2 to 1 + [BZ #24162] + +The offset in era-string format for Taisho gan-nen (1912) is currently +defined as 2, but it should be 1. So fix it. "Gan-nen" means the 1st +(origin) year, Taisho started on July 30, 1912. + +Reported-by: Morimitsu, Junji +Reviewed-by: Rafal Luzynski + +ChangeLog: + + [BZ #24162] + * localedata/locales/ja_JP (LC_TIME): Change the offset for Taisho + gan-nen from 2 to 1. Problem reported by Morimitsu, Junji. + +(cherry picked from commit 31effacee2fc1b327bedc9a5fcb4b83f227c6539) +--- + ChangeLog | 6 ++++++ + localedata/locales/ja_JP | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/ChangeLog b/ChangeLog +index 7111aeb149..048ca9644c 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2019-03-02 TAMUKI Shoichi ++ ++ [BZ #24162] ++ * localedata/locales/ja_JP (LC_TIME): Change the offset for Taisho ++ gan-nen from 2 to 1. Problem reported by Morimitsu, Junji. ++ + 2019-03-21 Stefan Liebler + + * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT): +diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP +index 1fd2fee44b..9bfbb2bb9b 100644 +--- a/localedata/locales/ja_JP ++++ b/localedata/locales/ja_JP +@@ -14951,7 +14951,7 @@ era "+:2:1990//01//01:+*::%EC%Ey";/ + "+:2:1927//01//01:1989//01//07::%EC%Ey";/ + "+:1:1926//12//25:1926//12//31::%EC";/ + "+:2:1913//01//01:1926//12//24::%EC%Ey";/ +- "+:2:1912//07//30:1912//12//31::%EC";/ ++ "+:1:1912//07//30:1912//12//31::%EC";/ + "+:6:1873//01//01:1912//07//29::%EC%Ey";/ + "+:1:0001//01//01:1872//12//31::%EC%Ey";/ + "+:1:-0001//12//31:-*::%EC%Ey" diff --git a/srcpkgs/glibc/template b/srcpkgs/glibc/template index 6f76817fb49..1e355ad8c64 100644 --- a/srcpkgs/glibc/template +++ b/srcpkgs/glibc/template @@ -1,7 +1,7 @@ # Template file for 'glibc' pkgname=glibc version=2.29 -revision=2 +revision=3 bootstrap=yes short_desc="GNU C library" maintainer="Juan RP "