From 01ba6f50762ad4fcd156a53ef7dbe671b64d3a5c Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Thu, 18 Jan 2018 16:47:06 +0000 Subject: Fix integer overflows in internal memalign and malloc [BZ #22343] [BZ #22774] When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT and a requested size close to SIZE_MAX, it falls back to malloc code (because the alignment of a block returned by malloc is sufficient to satisfy the call). In this case, an integer overflow in _int_malloc leads to posix_memalign incorrectly returning successfully. Upon fixing this and writing a somewhat thorough regression test, it was discovered that when posix_memalign is called with an alignment larger than MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size close to SIZE_MAX, a different integer overflow in _int_memalign leads to posix_memalign incorrectly returning successfully. Both integer overflows affect other memory allocation functions that use _int_malloc (one affected malloc in x86) or _int_memalign as well. This commit fixes both integer overflows. In addition to this, it adds a regression test to guard against false successful allocations by the following memory allocation functions when called with too-large allocation sizes and, where relevant, various valid alignments: malloc, realloc, calloc, reallocarray, memalign, posix_memalign, aligned_alloc, valloc, and pvalloc. (cherry picked from commit 8e448310d74b283c5cd02b9ed7fb997b47bf9b22) --- ChangeLog | 13 +++ NEWS | 8 ++ malloc/Makefile | 1 + malloc/malloc.c | 30 +++-- malloc/tst-malloc-too-large.c | 253 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 297 insertions(+), 8 deletions(-) create mode 100644 malloc/tst-malloc-too-large.c diff --git a/ChangeLog b/ChangeLog index e6add48bf5..60755b9163 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2018-01-18 Arjun Shankar + + [BZ #22343] + [BZ #22774] + CVE-2018-6485 + CVE-2018-6551 + * malloc/malloc.c (checked_request2size): call REQUEST_OUT_OF_RANGE + after padding. + (_int_memalign): check for integer overflow before calling + _int_malloc. + * malloc/tst-malloc-too-large.c: New test. + * malloc/Makefile: Add tst-malloc-too-large. + 2018-01-19 Tulio Magno Quites Machado Filho [BZ #22685] diff --git a/NEWS b/NEWS index 3f2cb5915f..0b0a6e8b5f 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,14 @@ Security related changes: succeeds without returning an absolute path due to unexpected behaviour of the Linux kernel getcwd syscall. Reported by halfdog. + CVE-2018-6485: The posix_memalign and memalign functions, when called with + an object size near the value of SIZE_MAX, would return a pointer to a + buffer which is too small, instead of NULL. Reported by Jakub Wilk. + + CVE-2018-6551: The malloc function, when called with an object size near + the value of SIZE_MAX, would return a pointer to a buffer which is too + small, instead of NULL. + The following bugs are resolved with this release: [16750] ldd: Never run file directly. diff --git a/malloc/Makefile b/malloc/Makefile index 9e23db9343..a50a93b252 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -35,6 +35,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-interpose-thread \ tst-alloc_buffer \ tst-malloc-tcache-leak \ + tst-malloc-too-large \ tests-static := \ tst-interpose-static-nothread \ diff --git a/malloc/malloc.c b/malloc/malloc.c index 6a52c288de..862337466e 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1231,14 +1231,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ MINSIZE : \ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) -/* Same, except also perform argument check */ - -#define checked_request2size(req, sz) \ - if (REQUEST_OUT_OF_RANGE (req)) { \ - __set_errno (ENOMEM); \ - return 0; \ - } \ - (sz) = request2size (req); +/* Same, except also perform an argument and result check. First, we check + that the padding done by request2size didn't result in an integer + overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting + size isn't so large that a later alignment would lead to another integer + overflow. */ +#define checked_request2size(req, sz) \ +({ \ + (sz) = request2size (req); \ + if (((sz) < (req)) \ + || REQUEST_OUT_OF_RANGE (sz)) \ + { \ + __set_errno (ENOMEM); \ + return 0; \ + } \ +}) /* --------------- Physical chunk operations --------------- @@ -4691,6 +4698,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) */ + /* Check for overflow. */ + if (nb > SIZE_MAX - alignment - MINSIZE) + { + __set_errno (ENOMEM); + return 0; + } + /* Call malloc with worst case padding to hit alignment. */ m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c new file mode 100644 index 0000000000..10fb136528 --- /dev/null +++ b/malloc/tst-malloc-too-large.c @@ -0,0 +1,253 @@ +/* Test and verify that too-large memory allocations fail with ENOMEM. + 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 + . */ + +/* Bug 22375 reported a regression in malloc where if after malloc'ing then + free'ing a small block of memory, malloc is then called with a really + large size argument (close to SIZE_MAX): instead of returning NULL and + setting errno to ENOMEM, malloc incorrectly returns the previously + allocated block instead. Bug 22343 reported a similar case where + posix_memalign incorrectly returns successfully when called with an with + a really large size argument. + + Both of these were caused by integer overflows in the allocator when it + was trying to pad the requested size to allow for book-keeping or + alignment. This test guards against such bugs by repeatedly allocating + and freeing small blocks of memory then trying to allocate various block + sizes larger than the memory bus width of 64-bit targets, or almost + as large as SIZE_MAX on 32-bit targets supported by glibc. In each case, + it verifies that such impossibly large allocations correctly fail. */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* This function prepares for each 'too-large memory allocation' test by + performing a small successful malloc/free and resetting errno prior to + the actual test. */ +static void +test_setup (void) +{ + void *volatile ptr = malloc (16); + TEST_VERIFY_EXIT (ptr != NULL); + free (ptr); + errno = 0; +} + + +/* This function tests each of: + - malloc (SIZE) + - realloc (PTR_FOR_REALLOC, SIZE) + - for various values of NMEMB: + - calloc (NMEMB, SIZE/NMEMB) + - calloc (SIZE/NMEMB, NMEMB) + - reallocarray (PTR_FOR_REALLOC, NMEMB, SIZE/NMEMB) + - reallocarray (PTR_FOR_REALLOC, SIZE/NMEMB, NMEMB) + and precedes each of these tests with a small malloc/free before it. */ +static void +test_large_allocations (size_t size) +{ + void * ptr_to_realloc; + + test_setup (); + TEST_VERIFY (malloc (size) == NULL); + TEST_VERIFY (errno == ENOMEM); + + ptr_to_realloc = malloc (16); + TEST_VERIFY_EXIT (ptr_to_realloc != NULL); + test_setup (); + TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL); + TEST_VERIFY (errno == ENOMEM); + free (ptr_to_realloc); + + for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2) + if ((size % nmemb) == 0) + { + test_setup (); + TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); + + test_setup (); + TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); + + ptr_to_realloc = malloc (16); + TEST_VERIFY_EXIT (ptr_to_realloc != NULL); + test_setup (); + TEST_VERIFY (reallocarray (ptr_to_realloc, nmemb, size / nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); + free (ptr_to_realloc); + + ptr_to_realloc = malloc (16); + TEST_VERIFY_EXIT (ptr_to_realloc != NULL); + test_setup (); + TEST_VERIFY (reallocarray (ptr_to_realloc, size / nmemb, nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); + free (ptr_to_realloc); + } + else + break; +} + + +static long pagesize; + +/* This function tests the following aligned memory allocation functions + using several valid alignments and precedes each allocation test with a + small malloc/free before it: + memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */ +static void +test_large_aligned_allocations (size_t size) +{ + /* ptr stores the result of posix_memalign but since all those calls + should fail, posix_memalign should never change ptr. We set it to + NULL here and later on we check that it remains NULL after each + posix_memalign call. */ + void * ptr = NULL; + + size_t align; + + /* All aligned memory allocation functions expect an alignment that is a + power of 2. Given this, we test each of them with every valid + alignment from 1 thru PAGESIZE. */ + for (align = 1; align <= pagesize; align *= 2) + { + test_setup (); + TEST_VERIFY (memalign (align, size) == NULL); + TEST_VERIFY (errno == ENOMEM); + + /* posix_memalign expects an alignment that is a power of 2 *and* a + multiple of sizeof (void *). */ + if ((align % sizeof (void *)) == 0) + { + test_setup (); + TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM); + TEST_VERIFY (ptr == NULL); + } + + /* aligned_alloc expects a size that is a multiple of alignment. */ + if ((size % align) == 0) + { + test_setup (); + TEST_VERIFY (aligned_alloc (align, size) == NULL); + TEST_VERIFY (errno == ENOMEM); + } + } + + /* Both valloc and pvalloc return page-aligned memory. */ + + test_setup (); + TEST_VERIFY (valloc (size) == NULL); + TEST_VERIFY (errno == ENOMEM); + + test_setup (); + TEST_VERIFY (pvalloc (size) == NULL); + TEST_VERIFY (errno == ENOMEM); +} + + +#define FOURTEEN_ON_BITS ((1UL << 14) - 1) +#define FIFTY_ON_BITS ((1UL << 50) - 1) + + +static int +do_test (void) +{ + +#if __WORDSIZE >= 64 + + /* This test assumes that none of the supported targets have an address + bus wider than 50 bits, and that therefore allocations for sizes wider + than 50 bits will fail. Here, we ensure that the assumption continues + to be true in the future when we might have address buses wider than 50 + bits. */ + + struct rlimit alloc_size_limit + = { + .rlim_cur = FIFTY_ON_BITS, + .rlim_max = FIFTY_ON_BITS + }; + + setrlimit (RLIMIT_AS, &alloc_size_limit); + +#endif /* __WORDSIZE >= 64 */ + + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* GCC 7 warns about too-large allocations; here we want to test + that they fail. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); +#endif + + /* Aligned memory allocation functions need to be tested up to alignment + size equivalent to page size, which should be a power of 2. */ + pagesize = sysconf (_SC_PAGESIZE); + TEST_VERIFY_EXIT (powerof2 (pagesize)); + + /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. + in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. + + We can expect that this range of allocation sizes will always lead to + an allocation failure on both 64 and 32 bit targets, because: + + 1. no currently supported 64-bit target has an address bus wider than + 50 bits -- and (2^64 - 2^14) is much wider than that; + + 2. on 32-bit targets, even though 2^32 is only 4 GB and potentially + addressable, glibc itself is more than 2^14 bytes in size, and + therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain + available. */ + + for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++) + { + test_large_allocations (SIZE_MAX - i); + test_large_aligned_allocations (SIZE_MAX - i); + } + +#if __WORDSIZE >= 64 + /* On 64-bit targets, we need to test a much wider range of too-large + sizes, so we test at intervals of (1 << 50) that allocation sizes + ranging from SIZE_MAX down to (1 << 50) fail: + The 14 MSBs are decremented starting from "all ON" going down to 1, + the 50 LSBs are "all ON" and then "all OFF" during every iteration. */ + for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--) + { + size_t size = (msbs << 50) | FIFTY_ON_BITS; + test_large_allocations (size); + test_large_aligned_allocations (size); + + size = msbs << 50; + test_large_allocations (size); + test_large_aligned_allocations (size); + } +#endif /* __WORDSIZE >= 64 */ + + DIAG_POP_NEEDS_COMMENT; + + return 0; +} + + +#include -- cgit 1.4.1 From d300041c533a3d837c9f37a099bcc95466860e98 Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Thu, 8 Feb 2018 17:04:17 +0100 Subject: Update NEWS for bug 22343 and bug 22774 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 0b0a6e8b5f..410f0d1631 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,7 @@ The following bugs are resolved with this release: [22321] sysconf: Fix missing definition of UIO_MAXIOV on Linux [22322] libc: [mips64] wrong bits/long-double.h installed [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671) + [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485) [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) [22377] Provide a C++ version of iseqsig [22636] PTHREAD_STACK_MIN is too small on x86-64 @@ -116,6 +117,7 @@ The following bugs are resolved with this release: (CVE-2018-1000001) [22685] powerpc: Fix syscalls during early process initialization [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE + [22774] malloc: Integer overflow in malloc (CVE-2018-6551) Version 2.26 -- cgit 1.4.1 From 7e7a5f0bcd28c6fc5285474f05080ac6ed5e55b9 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 17 May 2018 13:54:45 +0200 Subject: resolv: Fully initialize struct mmsghdr in send_dg [BZ #23037] (cherry picked from commit 583a27d525ae189bdfaa6784021b92a9a1dae12e) --- ChangeLog | 6 ++++++ NEWS | 1 + resolv/res_send.c | 40 +++++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60755b9163..8c1ff9d4b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-04-09 Florian Weimer + + [BZ #23037] + * resolv/res_send.c (send_dg): Use designated initializers instead + of assignment to zero-initialize other fields of struct mmsghdr. + 2018-01-18 Arjun Shankar [BZ #22343] diff --git a/NEWS b/NEWS index 410f0d1631..8c432b3e6e 100644 --- a/NEWS +++ b/NEWS @@ -118,6 +118,7 @@ The following bugs are resolved with this release: [22685] powerpc: Fix syscalls during early process initialization [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE [22774] malloc: Integer overflow in malloc (CVE-2018-6551) + [23037] resolv: Fully initialize struct mmsghdr in send_dg Version 2.26 diff --git a/resolv/res_send.c b/resolv/res_send.c index b396aae03c..0ca02f9843 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -1152,25 +1152,27 @@ send_dg(res_state statp, if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL && !single_request) { - struct iovec iov[2]; - struct mmsghdr reqs[2]; - reqs[0].msg_hdr.msg_name = NULL; - reqs[0].msg_hdr.msg_namelen = 0; - reqs[0].msg_hdr.msg_iov = &iov[0]; - reqs[0].msg_hdr.msg_iovlen = 1; - iov[0].iov_base = (void *) buf; - iov[0].iov_len = buflen; - reqs[0].msg_hdr.msg_control = NULL; - reqs[0].msg_hdr.msg_controllen = 0; - - reqs[1].msg_hdr.msg_name = NULL; - reqs[1].msg_hdr.msg_namelen = 0; - reqs[1].msg_hdr.msg_iov = &iov[1]; - reqs[1].msg_hdr.msg_iovlen = 1; - iov[1].iov_base = (void *) buf2; - iov[1].iov_len = buflen2; - reqs[1].msg_hdr.msg_control = NULL; - reqs[1].msg_hdr.msg_controllen = 0; + struct iovec iov = + { .iov_base = (void *) buf, .iov_len = buflen }; + struct iovec iov2 = + { .iov_base = (void *) buf2, .iov_len = buflen2 }; + struct mmsghdr reqs[2] = + { + { + .msg_hdr = + { + .msg_iov = &iov, + .msg_iovlen = 1, + }, + }, + { + .msg_hdr = + { + .msg_iov = &iov2, + .msg_iovlen = 1, + } + }, + }; int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL); if (__glibc_likely (ndg == 2)) -- cgit 1.4.1 From 1f7c4748d611445065f911ced519b7fb49f82ad5 Mon Sep 17 00:00:00 2001 From: Jesse Hathaway Date: Thu, 17 May 2018 13:56:33 +0200 Subject: getlogin_r: return early when linux sentinel value is set When there is no login uid Linux sets /proc/self/loginid to the sentinel value of, (uid_t) -1. If this is set we can return early and avoid needlessly looking up the sentinel value in any configured nss databases. Checked on aarch64-linux-gnu. * sysdeps/unix/sysv/linux/getlogin_r.c (__getlogin_r_loginuid): Return early when linux sentinel value is set. Reviewed-by: Adhemerval Zanella (cherry picked from commit cc8a1620eb97ccddd337d157263c13c57b39ab71) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/unix/sysv/linux/getlogin_r.c | 9 +++++++++ 3 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8c1ff9d4b2..da8d9a5190 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-03-27 Jesse Hathaway + + [BZ #23024] + * sysdeps/unix/sysv/linux/getlogin_r.c (__getlogin_r_loginuid): Return + early when linux sentinel value is set. + 2018-04-09 Florian Weimer [BZ #23037] diff --git a/NEWS b/NEWS index 8c432b3e6e..dcbb2b0ff6 100644 --- a/NEWS +++ b/NEWS @@ -118,6 +118,7 @@ The following bugs are resolved with this release: [22685] powerpc: Fix syscalls during early process initialization [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE [22774] malloc: Integer overflow in malloc (CVE-2018-6551) + [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg Version 2.26 diff --git a/sysdeps/unix/sysv/linux/getlogin_r.c b/sysdeps/unix/sysv/linux/getlogin_r.c index 05ac36b491..fe81fd196a 100644 --- a/sysdeps/unix/sysv/linux/getlogin_r.c +++ b/sysdeps/unix/sysv/linux/getlogin_r.c @@ -54,6 +54,15 @@ __getlogin_r_loginuid (char *name, size_t namesize) endp == uidbuf || *endp != '\0')) return -1; + /* If there is no login uid, linux sets /proc/self/loginid to the sentinel + value of, (uid_t) -1, so check if that value is set and return early to + avoid making unneeded nss lookups. */ + if (uid == (uid_t) -1) + { + __set_errno (ENXIO); + return ENXIO; + } + size_t buflen = 1024; char *buf = alloca (buflen); bool use_malloc = false; -- cgit 1.4.1 From 31e2d15b808e6c3bd7406eb0c1bef8d76ec6abe2 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Thu, 17 May 2018 13:57:29 +0200 Subject: Fix crash in resolver on memory allocation failure (bug 23005) (cherry picked from commit f178e59fa5eefbbd37fde040ae8334aa5c857ee1) --- ChangeLog | 6 ++++++ NEWS | 1 + resolv/res_send.c | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index da8d9a5190..05a15bc72e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-03-27 Andreas Schwab + + [BZ #23005] + * resolv/res_send.c (__res_context_send): Return ENOMEM if + allocation of private copy of nsaddr_list fails. + 2018-03-27 Jesse Hathaway [BZ #23024] diff --git a/NEWS b/NEWS index dcbb2b0ff6..4d360a426e 100644 --- a/NEWS +++ b/NEWS @@ -118,6 +118,7 @@ The following bugs are resolved with this release: [22685] powerpc: Fix syscalls during early process initialization [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE [22774] malloc: Integer overflow in malloc (CVE-2018-6551) + [23005] resolv: Fix crash in resolver on memory allocation failure [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg diff --git a/resolv/res_send.c b/resolv/res_send.c index 0ca02f9843..83f35f60da 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -471,6 +471,11 @@ __res_context_send (struct resolv_context *ctx, '\0', sizeof (struct sockaddr_in6) - sizeof (struct sockaddr_in)); + else + { + __set_errno (ENOMEM); + return -1; + } } EXT(statp).nscount = statp->nscount; } -- cgit 1.4.1 From 71d339cb86dc58aa511dd1544dad2c77d075069c Mon Sep 17 00:00:00 2001 From: Andrew Senkevich Date: Thu, 17 May 2018 13:58:21 +0200 Subject: Fix i386 memmove issue (bug 22644). [BZ #22644] * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed branch conditions. * string/test-memmove.c (do_test2): New testcase. (cherry picked from commit cd66c0e584c6d692bc8347b5e72723d02b8a8ada) --- ChangeLog | 8 +++ NEWS | 1 + string/test-memmove.c | 58 ++++++++++++++++++++++ .../i386/i686/multiarch/memcpy-sse2-unaligned.S | 12 ++--- 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05a15bc72e..a32ba57fc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-03-23 Andrew Senkevich + Max Horn + + [BZ #22644] + * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed + branch conditions. + * string/test-memmove.c (do_test2): New testcase. + 2018-03-27 Andreas Schwab [BZ #23005] diff --git a/NEWS b/NEWS index 4d360a426e..a8016a054a 100644 --- a/NEWS +++ b/NEWS @@ -113,6 +113,7 @@ The following bugs are resolved with this release: [22636] PTHREAD_STACK_MIN is too small on x86-64 [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice [22637] nptl: Fix stack guard size accounting + [22644] Fix i386 memmove issue [22679] getcwd(3) can succeed without returning an absolute path (CVE-2018-1000001) [22685] powerpc: Fix syscalls during early process initialization diff --git a/string/test-memmove.c b/string/test-memmove.c index 51f79f6eb4..60f77f825b 100644 --- a/string/test-memmove.c +++ b/string/test-memmove.c @@ -24,6 +24,7 @@ # define TEST_NAME "memmove" #endif #include "test-string.h" +#include char *simple_memmove (char *, const char *, size_t); @@ -245,6 +246,60 @@ do_random_tests (void) } } +static void +do_test2 (void) +{ + size_t size = 0x20000000; + uint32_t * large_buf; + + large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + + if (large_buf == MAP_FAILED) + error (EXIT_UNSUPPORTED, errno, "Large mmap failed"); + + if ((uintptr_t) large_buf > 0x80000000 - 128 + || 0x80000000 - (uintptr_t) large_buf > 0x20000000) + { + error (0, 0, "Large mmap allocated improperly"); + ret = EXIT_UNSUPPORTED; + munmap ((void *) large_buf, size); + return; + } + + size_t bytes_move = 0x80000000 - (uintptr_t) large_buf; + size_t arr_size = bytes_move / sizeof (uint32_t); + size_t i; + + FOR_EACH_IMPL (impl, 0) + { + for (i = 0; i < arr_size; i++) + large_buf[i] = (uint32_t) i; + + uint32_t * dst = &large_buf[33]; + +#ifdef TEST_BCOPY + CALL (impl, (char *) large_buf, (char *) dst, bytes_move); +#else + CALL (impl, (char *) dst, (char *) large_buf, bytes_move); +#endif + + for (i = 0; i < arr_size; i++) + { + if (dst[i] != (uint32_t) i) + { + error (0, 0, + "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", + impl->name, dst, large_buf, i); + ret = 1; + break; + } + } + } + + munmap ((void *) large_buf, size); +} + int test_main (void) { @@ -284,6 +339,9 @@ test_main (void) } do_random_tests (); + + do_test2 (); + return ret; } diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S index 2fe2072cb1..043f4260e2 100644 --- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S @@ -72,7 +72,7 @@ ENTRY (MEMCPY) cmp %edx, %eax # ifdef USE_AS_MEMMOVE - jg L(check_forward) + ja L(check_forward) L(mm_len_0_or_more_backward): /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128] @@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward): jbe L(mm_len_0_16_bytes_backward) cmpl $32, %ecx - jg L(mm_len_32_or_more_backward) + ja L(mm_len_32_or_more_backward) /* Copy [0..32] and return. */ movdqu (%eax), %xmm0 @@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward): L(mm_len_32_or_more_backward): cmpl $64, %ecx - jg L(mm_len_64_or_more_backward) + ja L(mm_len_64_or_more_backward) /* Copy [0..64] and return. */ movdqu (%eax), %xmm0 @@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward): L(mm_len_64_or_more_backward): cmpl $128, %ecx - jg L(mm_len_128_or_more_backward) + ja L(mm_len_128_or_more_backward) /* Copy [0..128] and return. */ movdqu (%eax), %xmm0 @@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward): add %ecx, %eax cmp %edx, %eax movl SRC(%esp), %eax - jle L(forward) + jbe L(forward) PUSH (%esi) PUSH (%edi) PUSH (%ebx) @@ -269,7 +269,7 @@ L(check_forward): add %edx, %ecx cmp %eax, %ecx movl LEN(%esp), %ecx - jle L(forward) + jbe L(forward) /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128] separately. */ -- cgit 1.4.1 From 677e6d13e0d59b35720b4d71af4a8d9038aedc6a Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Thu, 1 Mar 2018 23:20:45 -0500 Subject: [BZ #22342] Fix netgroup cache keys. Unlike other nscd caches, the netgroup cache contains two types of records - those for "iterate through a netgroup" (i.e. setnetgrent()) and those for "is this user in this netgroup" (i.e. innetgr()), i.e. full and partial records. The timeout code assumes these records have the same key for the group name, so that the collection of records that is "this netgroup" can be expired as a unit. However, the keys are not the same, as the in-netgroup key is generated by nscd rather than being passed to it from elsewhere, and is generated without the trailing NUL. All other keys have the trailing NUL, and as noted in the linked BZ, debug statements confirm that two keys for the same netgroup are added to the cache with two different lengths. The result of this is that as records in the cache expire, the purge code only cleans out one of the two types of entries, resulting in stale, possibly incorrect, and possibly inconsistent cache data. The patch simply includes the existing NUL in the computation for the key length ('key' points to the char after the NUL, and 'group' to the first char of the group, so 'key-group' includes the first char to the NUL, inclusive). [BZ #22342] * nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in key value. Reviewed-by: Carlos O'Donell (cherry picked from commit 1c81d55fc4b07b51adf68558ba74ce975153e580) --- ChangeLog | 6 ++++++ NEWS | 1 + nscd/netgroupcache.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a32ba57fc3..89df4d1577 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-03-01 DJ Delorie + + [BZ #22342] + * nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in + key value. + 2018-03-23 Andrew Senkevich Max Horn diff --git a/NEWS b/NEWS index a8016a054a..4deb16c7c7 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,7 @@ The following bugs are resolved with this release: [22321] sysconf: Fix missing definition of UIO_MAXIOV on Linux [22322] libc: [mips64] wrong bits/long-double.h installed [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671) + [22342] NSCD not properly caching netgroup [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485) [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) [22377] Provide a C++ version of iseqsig diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index cd0c3ea19b..741c3bba2b 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -480,7 +480,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, { const char *group = key; key = (char *) rawmemchr (key, '\0') + 1; - size_t group_len = key - group - 1; + size_t group_len = key - group; const char *host = *key++ ? key : NULL; if (host != NULL) key = (char *) rawmemchr (key, '\0') + 1; -- cgit 1.4.1 From 3241353ab20b4cc8798088d456ffa9aace1514de Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Fri, 17 Nov 2017 16:04:29 -0200 Subject: i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) This patch fixes the i386 sa_restorer field initialization for sigaction syscall for kernel with vDSO. As described in bug report, i386 Linux (and compat on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a request for stack switching if the SS segment is 'funny'. This means that anything that tries to mix glibc's signal handling with segmentation (for instance through modify_ldt syscall) is randomly broken depending on what values lands in sa_restorer. The testcase added is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, more specifically in do_multicpu_tests function. The main changes are: - C11 atomics instead of plain access. - Remove x86_64 support which simplifies the syscall handling and fallbacks. - Replicate only the test required to trigger the issue. Checked on i686-linux-gnu. [BZ #21269] * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269. * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear sa_restorer for vDSO case. * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file. (cherry picked from commit 68448be208ee06e76665918b37b0a57e3e00c8b4) --- ChangeLog | 8 + NEWS | 1 + sysdeps/unix/sysv/linux/i386/Makefile | 3 + sysdeps/unix/sysv/linux/i386/sigaction.c | 3 +- sysdeps/unix/sysv/linux/i386/tst-bz21269.c | 233 +++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 sysdeps/unix/sysv/linux/i386/tst-bz21269.c diff --git a/ChangeLog b/ChangeLog index 89df4d1577..598e59de0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-03-03 Adhemerval Zanella + + [BZ #21269] + * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269. + * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear + sa_restorer for vDSO case. + * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file. + 2018-03-01 DJ Delorie [BZ #22342] diff --git a/NEWS b/NEWS index 4deb16c7c7..106c7e0a73 100644 --- a/NEWS +++ b/NEWS @@ -78,6 +78,7 @@ The following bugs are resolved with this release: [20532] getaddrinfo: More robust handling of dlopen failures [21242] assert: Suppress pedantic warning caused by statement expression [21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve + [21269] i386 sigaction sa_restorer handling is wrong [21780] posix: Set p{read,write}v2 to return ENOTSUP [21871] x86-64: Use _dl_runtime_resolve_opt only with AVX512F [21885] getaddrinfo: Release resolver context on error in gethosts diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index 4080b8c966..da716e2c1b 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -3,6 +3,9 @@ default-abi := 32 ifeq ($(subdir),misc) sysdep_routines += ioperm iopl vm86 + +tests += tst-bz21269 +$(objpfx)tst-bz21269: $(shared-thread-library) endif ifeq ($(subdir),elf) diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c index 0cc9d67ad9..1cad07b26c 100644 --- a/sysdeps/unix/sysv/linux/i386/sigaction.c +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c @@ -42,7 +42,6 @@ extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; #endif extern void restore (void) asm ("__restore") attribute_hidden; - /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ int @@ -65,6 +64,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore); } + else + kact.sa_restorer = NULL; } /* XXX The size argument hopefully will have to be changed to the diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c new file mode 100644 index 0000000000..353e36507d --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c @@ -0,0 +1,233 @@ +/* Test for i386 sigaction sa_restorer handling (BZ#21269) + Copyright (C) 2017 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 + . */ + +/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, + more specifically in do_multicpu_tests function. The main changes + are: + + - C11 atomics instead of plain access. + - Remove x86_64 support which simplifies the syscall handling + and fallbacks. + - Replicate only the test required to trigger the issue for the + BZ#21269. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static int +xset_thread_area (struct user_desc *u_info) +{ + long ret = syscall (SYS_set_thread_area, u_info); + TEST_VERIFY_EXIT (ret == 0); + return ret; +} + +static void +xmodify_ldt (int func, const void *ptr, unsigned long bytecount) +{ + TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0); +} + +static int +futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2, + int val3) +{ + return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); +} + +static void +xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags) +{ + struct sigaction sa = { 0 }; + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0); + TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0); +} + +static jmp_buf jmpbuf; + +static void +sigsegv_handler (int sig, siginfo_t *info, void *ctx_void) +{ + siglongjmp (jmpbuf, 1); +} + +/* Points to an array of 1024 ints, each holding its own index. */ +static const unsigned int *counter_page; +static struct user_desc *low_user_desc; +static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry. */ +static int gdt_entry_num; + +static void +setup_counter_page (void) +{ + long page_size = sysconf (_SC_PAGE_SIZE); + TEST_VERIFY_EXIT (page_size > 0); + unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); + for (int i = 0; i < (page_size / sizeof (unsigned int)); i++) + page[i] = i; + counter_page = page; +} + +static void +setup_low_user_desc (void) +{ + low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc), + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); + + low_user_desc->entry_number = -1; + low_user_desc->base_addr = (unsigned long) &counter_page[1]; + low_user_desc->limit = 0xffff; + low_user_desc->seg_32bit = 1; + low_user_desc->contents = 0; + low_user_desc->read_exec_only = 0; + low_user_desc->limit_in_pages = 1; + low_user_desc->seg_not_present = 0; + low_user_desc->useable = 0; + + xset_thread_area (low_user_desc); + + low_user_desc_clear = low_user_desc + 1; + low_user_desc_clear->entry_number = gdt_entry_num; + low_user_desc_clear->read_exec_only = 1; + low_user_desc_clear->seg_not_present = 1; +} + +/* Possible values of futex: + 0: thread is idle. + 1: thread armed. + 2: thread should clear LDT entry 0. + 3: thread should exit. */ +static atomic_uint ftx; + +static void * +threadproc (void *ctx) +{ + while (1) + { + futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); + while (atomic_load (&ftx) != 2) + { + if (atomic_load (&ftx) >= 3) + return NULL; + } + + /* clear LDT entry 0. */ + const struct user_desc desc = { 0 }; + xmodify_ldt (1, &desc, sizeof (desc)); + + /* If ftx == 2, set it to zero, If ftx == 100, quit. */ + if (atomic_fetch_add (&ftx, -2) != 2) + return NULL; + } +} + + +/* As described in testcase, for historical reasons x86_32 Linux (and compat + on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a + request for stack switching if the SS segment is 'funny' (this is default + scenario for vDSO system). This means that anything that tries to mix + signal handling with segmentation should explicit clear the sa_restorer. + + This testcase check if sigaction in fact does it by changing the local + descriptor table (LDT) through the modify_ldt syscall and triggering + a synchronous segfault on iret fault by trying to install an invalid + segment. With a correct zeroed sa_restorer it should not trigger an + 'real' SEGSEGV and allows the siglongjmp in signal handler. */ + +static int +do_test (void) +{ + setup_counter_page (); + setup_low_user_desc (); + + pthread_t thread; + unsigned short orig_ss; + + xsethandler (SIGSEGV, sigsegv_handler, 0); + /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ + xsethandler (SIGILL, sigsegv_handler, 0); + + thread = xpthread_create (0, threadproc, 0); + + asm volatile ("mov %%ss, %0" : "=rm" (orig_ss)); + + for (int i = 0; i < 5; i++) + { + if (sigsetjmp (jmpbuf, 1) != 0) + continue; + + /* Make sure the thread is ready after the last test. */ + while (atomic_load (&ftx) != 0) + ; + + struct user_desc desc = { + .entry_number = 0, + .base_addr = 0, + .limit = 0xffff, + .seg_32bit = 1, + .contents = 0, + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 0 + }; + + xmodify_ldt (0x11, &desc, sizeof (desc)); + + /* Arm the thread. */ + ftx = 1; + futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + asm volatile ("mov %0, %%ss" : : "r" (0x7)); + + /* Fire up thread modify_ldt call. */ + atomic_store (&ftx, 2); + + while (atomic_load (&ftx) != 0) + ; + + /* On success, modify_ldt will segfault us synchronously and we will + escape via siglongjmp. */ + support_record_failure (); + } + + atomic_store (&ftx, 100); + futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + xpthread_join (thread); + + return 0; +} + +#include -- cgit 1.4.1 From 02f0dd83a4abf190f13eef8d70811a7c8ec896ad Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 17 May 2018 14:04:58 +0200 Subject: Fix signed integer overflow in random_r (bug 17343). Bug 17343 reports that stdlib/random_r.c has code with undefined behavior because of signed integer overflow on int32_t. This patch changes the code so that the possibly overflowing computations use unsigned arithmetic instead. Note that the bug report refers to "Most code" in that file. The places changed in this patch are the only ones I found where I think such overflow can occur. Tested for x86_64 and x86. [BZ #17343] * stdlib/random_r.c (__random_r): Use unsigned arithmetic for possibly overflowing computations. (cherry picked from commit 8a07b0c43c46a480da070efd53a2720195e2256f) --- ChangeLog | 6 ++++++ NEWS | 1 + stdlib/random_r.c | 9 ++++----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 598e59de0e..dbae1b9270 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-03-20 Joseph Myers + + [BZ #17343] + * stdlib/random_r.c (__random_r): Use unsigned arithmetic for + possibly overflowing computations. + 2018-03-03 Adhemerval Zanella [BZ #21269] diff --git a/NEWS b/NEWS index 106c7e0a73..7c1526004f 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,7 @@ Security related changes: The following bugs are resolved with this release: [16750] ldd: Never run file directly. + [17343] Fix signed integer overflow in random_r [17956] crypt: Use NSPR header files in addition to NSS header files [20532] getaddrinfo: More robust handling of dlopen failures [21242] assert: Suppress pedantic warning caused by statement expression diff --git a/stdlib/random_r.c b/stdlib/random_r.c index c3f6f9aede..150fa9bb34 100644 --- a/stdlib/random_r.c +++ b/stdlib/random_r.c @@ -361,8 +361,7 @@ __random_r (struct random_data *buf, int32_t *result) if (buf->rand_type == TYPE_0) { - int32_t val = state[0]; - val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; + int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff; state[0] = val; *result = val; } @@ -371,11 +370,11 @@ __random_r (struct random_data *buf, int32_t *result) int32_t *fptr = buf->fptr; int32_t *rptr = buf->rptr; int32_t *end_ptr = buf->end_ptr; - int32_t val; + uint32_t val; - val = *fptr += *rptr; + val = *fptr += (uint32_t) *rptr; /* Chucking least random bit. */ - *result = (val >> 1) & 0x7fffffff; + *result = val >> 1; ++fptr; if (fptr >= end_ptr) { -- cgit 1.4.1 From be056fae3bc1fe1019761a4b4994e808344b05e1 Mon Sep 17 00:00:00 2001 From: Stefan Liebler Date: Thu, 17 May 2018 14:05:51 +0200 Subject: Fix blocking pthread_join. [BZ #23137] On s390 (31bit) if glibc is build with -Os, pthread_join sometimes blocks indefinitely. This is e.g. observable with testcase intl/tst-gettext6. pthread_join is calling lll_wait_tid(tid), which performs the futex-wait syscall in a loop as long as tid != 0 (thread is alive). On s390 (and build with -Os), tid is loaded from memory before comparing against zero and then the tid is loaded a second time in order to pass it to the futex-wait-syscall. If the thread exits in between, then the futex-wait-syscall is called with the value zero and it waits until a futex-wake occurs. As the thread is already exited, there won't be a futex-wake. In lll_wait_tid, the tid is stored to the local variable __tid, which is then used as argument for the futex-wait-syscall. But unfortunately the compiler is allowed to reload the value from memory. With this patch, the tid is loaded with atomic_load_acquire. Then the compiler is not allowed to reload the value for __tid from memory. ChangeLog: [BZ #23137] * sysdeps/nptl/lowlevellock.h (lll_wait_tid): Use atomic_load_acquire to load __tid. (cherry picked from commit 1660901840dfc9fde6c5720a32f901af6f08f00a) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/nptl/lowlevellock.h | 13 ++++++++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index dbae1b9270..488bd789b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-05-04 Stefan Liebler + + [BZ #23137] + * sysdeps/nptl/lowlevellock.h (lll_wait_tid): + Use atomic_load_acquire to load __tid. + 2018-03-20 Joseph Myers [BZ #17343] diff --git a/NEWS b/NEWS index 7c1526004f..8a2da5091f 100644 --- a/NEWS +++ b/NEWS @@ -125,6 +125,7 @@ The following bugs are resolved with this release: [23005] resolv: Fix crash in resolver on memory allocation failure [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg + [23137] s390: Fix blocking pthread_join Version 2.26 diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h index 54e3c28b0b..649aea813c 100644 --- a/sysdeps/nptl/lowlevellock.h +++ b/sysdeps/nptl/lowlevellock.h @@ -181,11 +181,14 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *, thread ID while the clone is running and is reset to zero by the kernel afterwards. The kernel up to version 3.16.3 does not use the private futex operations for futex wake-up when the clone terminates. */ -#define lll_wait_tid(tid) \ - do { \ - __typeof (tid) __tid; \ - while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid, LLL_SHARED);\ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + /* We need acquire MO here so that we synchronize \ + with the kernel's store to 0 when the clone \ + terminates. (see above) */ \ + while ((__tid = atomic_load_acquire (&(tid))) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ } while (0) extern int __lll_timedwait_tid (int *, const struct timespec *) -- cgit 1.4.1 From 365722ace6c9bad3167804fa8f12884eafae6d8f Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Sat, 5 May 2018 18:08:27 -0700 Subject: Fix stack overflow with huge PT_NOTE segment [BZ #20419] A PT_NOTE in a binary could be arbitratily large, so using alloca for it may cause stack overflow. If the note is larger than __MAX_ALLOCA_CUTOFF, use dynamically allocated memory to read it in. 2018-05-05 Paul Pluzhnikov [BZ #20419] * elf/dl-load.c (open_verify): Fix stack overflow. * elf/Makefile (tst-big-note): New test. * elf/tst-big-note-lib.S: New. * elf/tst-big-note.c: New. (cherry picked from commit 0065aaaaae51cd60210ec3a7e13dddd8e01ffe2c) --- ChangeLog | 8 ++++++++ NEWS | 1 + elf/Makefile | 9 +++++++-- elf/dl-load.c | 21 +++++++++++++++++++-- elf/tst-big-note-lib.S | 26 ++++++++++++++++++++++++++ elf/tst-big-note.c | 26 ++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 elf/tst-big-note-lib.S create mode 100644 elf/tst-big-note.c diff --git a/ChangeLog b/ChangeLog index 488bd789b8..0bda4a3d1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-05-05 Paul Pluzhnikov + + [BZ #20419] + * elf/dl-load.c (open_verify): Fix stack overflow. + * elf/Makefile (tst-big-note): New test. + * elf/tst-big-note-lib.S: New. + * elf/tst-big-note.c: New. + 2018-05-04 Stefan Liebler [BZ #23137] diff --git a/NEWS b/NEWS index 8a2da5091f..7f5b68a006 100644 --- a/NEWS +++ b/NEWS @@ -76,6 +76,7 @@ The following bugs are resolved with this release: [16750] ldd: Never run file directly. [17343] Fix signed integer overflow in random_r [17956] crypt: Use NSPR header files in addition to NSS header files + [20419] elf: Fix stack overflow with huge PT_NOTE segment [20532] getaddrinfo: More robust handling of dlopen failures [21242] assert: Suppress pedantic warning caused by statement expression [21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve diff --git a/elf/Makefile b/elf/Makefile index e758a4c960..c2d5269d80 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -179,7 +179,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ - tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose + tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ + tst-big-note # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -263,7 +264,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ - tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin + tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ + tst-big-note-lib + ifeq (yes,$(have-mtls-dialect-gnu2)) tests += tst-gnu2-tls1 modules-names += tst-gnu2-tls1mod @@ -1410,3 +1413,5 @@ tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \ LD_HWCAP_MASK=0x1 tst-env-setuid-tunables-ENV = \ GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096 + +$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so diff --git a/elf/dl-load.c b/elf/dl-load.c index 7397c1882c..127be5beca 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1520,6 +1520,7 @@ open_verify (const char *name, int fd, ElfW(Ehdr) *ehdr; ElfW(Phdr) *phdr, *ph; ElfW(Word) *abi_note; + ElfW(Word) *abi_note_malloced = NULL; unsigned int osversion; size_t maplength; @@ -1679,10 +1680,25 @@ open_verify (const char *name, int fd, abi_note = (void *) (fbp->buf + ph->p_offset); else { - abi_note = alloca (size); + /* Note: __libc_use_alloca is not usable here, because + thread info may not have been set up yet. */ + if (size < __MAX_ALLOCA_CUTOFF) + abi_note = alloca (size); + else + { + /* There could be multiple PT_NOTEs. */ + abi_note_malloced = realloc (abi_note_malloced, size); + if (abi_note_malloced == NULL) + goto read_error; + + abi_note = abi_note_malloced; + } __lseek (fd, ph->p_offset, SEEK_SET); if (__libc_read (fd, (void *) abi_note, size) != size) - goto read_error; + { + free (abi_note_malloced); + goto read_error; + } } while (memcmp (abi_note, &expected_note, sizeof (expected_note))) @@ -1718,6 +1734,7 @@ open_verify (const char *name, int fd, break; } + free (abi_note_malloced); } return fd; diff --git a/elf/tst-big-note-lib.S b/elf/tst-big-note-lib.S new file mode 100644 index 0000000000..6b514a03cc --- /dev/null +++ b/elf/tst-big-note-lib.S @@ -0,0 +1,26 @@ +/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify() + 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 + . */ + +/* This creates a .so with 8MiB PT_NOTE segment. + On a typical Linux system with 8MiB "ulimit -s", that was enough + to trigger stack overflow in open_verify. */ + +.pushsection .note.big,"a" +.balign 4 +.fill 8*1024*1024, 1, 0 +.popsection diff --git a/elf/tst-big-note.c b/elf/tst-big-note.c new file mode 100644 index 0000000000..fcd2b0ed82 --- /dev/null +++ b/elf/tst-big-note.c @@ -0,0 +1,26 @@ +/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify() + 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 + . */ + +/* This file must be run from within a directory called "elf". */ + +int main (int argc, char *argv[]) +{ + /* Nothing to do here: merely linking against tst-big-note-lib.so triggers + the bug. */ + return 0; +} -- cgit 1.4.1 From af7519f7b35024224c163e32a89fb247b0c446fc Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Tue, 8 May 2018 18:12:41 -0700 Subject: Fix path length overflow in realpath [BZ #22786] Integer addition overflow may cause stack buffer overflow when realpath() input length is close to SSIZE_MAX. 2018-05-09 Paul Pluzhnikov [BZ #22786] * stdlib/canonicalize.c (__realpath): Fix overflow in path length computation. * stdlib/Makefile (test-bz22786): New test. * stdlib/test-bz22786.c: New test. (cherry picked from commit 5460617d1567657621107d895ee2dd83bc1f88f2) --- ChangeLog | 8 +++++ NEWS | 1 + stdlib/Makefile | 2 +- stdlib/canonicalize.c | 2 +- stdlib/test-bz22786.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 stdlib/test-bz22786.c diff --git a/ChangeLog b/ChangeLog index 0bda4a3d1b..f92be1355d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-05-09 Paul Pluzhnikov + + [BZ #22786] + * stdlib/canonicalize.c (__realpath): Fix overflow in path length + computation. + * stdlib/Makefile (test-bz22786): New test. + * stdlib/test-bz22786.c: New test. + 2018-05-05 Paul Pluzhnikov [BZ #20419] diff --git a/NEWS b/NEWS index 7f5b68a006..d5daa3adc5 100644 --- a/NEWS +++ b/NEWS @@ -121,6 +121,7 @@ The following bugs are resolved with this release: [22679] getcwd(3) can succeed without returning an absolute path (CVE-2018-1000001) [22685] powerpc: Fix syscalls during early process initialization + [22786] Fix path length overflow in realpath [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE [22774] malloc: Integer overflow in malloc (CVE-2018-6551) [23005] resolv: Fix crash in resolver on memory allocation failure diff --git a/stdlib/Makefile b/stdlib/Makefile index 0314d5926b..5cdc91050c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -80,7 +80,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l \ tst-quick_exit tst-thread-quick_exit tst-width \ tst-width-stdint tst-strfrom tst-strfrom-locale \ - tst-getrandom + tst-getrandom test-bz22786 tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ tst-tls-atexit tst-tls-atexit-nodelete tests-static := tst-secure-getenv diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index c3d892c862..a497d06454 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved) extra_buf = __alloca (path_max); len = strlen (end); - if ((long int) (n + len) >= path_max) + if (path_max - n <= len) { __set_errno (ENAMETOOLONG); goto error; diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c new file mode 100644 index 0000000000..e7837f98c1 --- /dev/null +++ b/stdlib/test-bz22786.c @@ -0,0 +1,90 @@ +/* Bug 22786: test for buffer overflow in realpath. + 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 + . */ + +/* This file must be run from within a directory called "stdlib". */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + const char dir[] = "bz22786"; + const char lnk[] = "bz22786/symlink"; + + rmdir (dir); + if (mkdir (dir, 0755) != 0 && errno != EEXIST) + { + printf ("mkdir %s: %m\n", dir); + return EXIT_FAILURE; + } + if (symlink (".", lnk) != 0 && errno != EEXIST) + { + printf ("symlink (%s, %s): %m\n", dir, lnk); + return EXIT_FAILURE; + } + + const size_t path_len = (size_t) INT_MAX + 1; + + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* GCC 7 warns about too-large allocations; here we need such + allocation to succeed for the test to work. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); +#endif + char *path = malloc (path_len); + DIAG_POP_NEEDS_COMMENT; + + if (path == NULL) + { + printf ("malloc (%zu): %m\n", path_len); + return EXIT_UNSUPPORTED; + } + + /* Construct very long path = "bz22786/symlink/aaaa....." */ + char *p = mempcpy (path, lnk, sizeof (lnk) - 1); + *(p++) = '/'; + memset (p, 'a', path_len - (path - p) - 2); + p[path_len - (path - p) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ + p = realpath (path, NULL); + + if (p != NULL || errno != ENAMETOOLONG) + { + printf ("realpath: %s (%m)", p); + return EXIT_FAILURE; + } + + /* Cleanup. */ + unlink (lnk); + rmdir (dir); + + return 0; +} + +#define TEST_FUNCTION do_test +#include -- cgit 1.4.1 From 6b4362f2cbb6ef6e265d9f216f3c13d84405a1c0 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Thu, 24 May 2018 14:39:18 +0200 Subject: Don't write beyond destination in __mempcpy_avx512_no_vzeroupper (bug 23196) When compiled as mempcpy, the return value is the end of the destination buffer, thus it cannot be used to refer to the start of it. (cherry picked from commit 9aaaab7c6e4176e61c59b0a63c6ba906d875dc0e) --- ChangeLog | 9 +++++++++ NEWS | 5 +++++ string/test-mempcpy.c | 1 + sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S | 5 +++-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f92be1355d..e956dd3d66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2018-05-23 Andreas Schwab + + [BZ #23196] + CVE-2018-11237 + * sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S + (L(preloop_large)): Save initial destination pointer in %r11 and + use it instead of %rax after the loop. + * string/test-mempcpy.c (MIN_PAGE_SIZE): Define. + 2018-05-09 Paul Pluzhnikov [BZ #22786] diff --git a/NEWS b/NEWS index d5daa3adc5..c3c6aff8fc 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,10 @@ Security related changes: the value of SIZE_MAX, would return a pointer to a buffer which is too small, instead of NULL. + CVE-2018-11237: The mempcpy implementation for the Intel Xeon Phi + architecture could write beyond the target buffer, resulting in a buffer + overflow. Reported by Andreas Schwab. + The following bugs are resolved with this release: [16750] ldd: Never run file directly. @@ -128,6 +132,7 @@ The following bugs are resolved with this release: [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg [23137] s390: Fix blocking pthread_join + [23196] __mempcpy_avx512_no_vzeroupper mishandles large copies Version 2.26 diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c index 364a811c62..ec11c9f6e6 100644 --- a/string/test-mempcpy.c +++ b/string/test-mempcpy.c @@ -18,6 +18,7 @@ . */ #define MEMCPY_RESULT(dst, len) (dst) + (len) +#define MIN_PAGE_SIZE 131072 #define TEST_MAIN #define TEST_NAME "mempcpy" #include "test-string.h" diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S index f3ef10577c..ae84ddc667 100644 --- a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S +++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S @@ -340,6 +340,7 @@ L(preloop_large): vmovups (%rsi), %zmm4 vmovups 0x40(%rsi), %zmm5 + mov %rdi, %r11 /* Align destination for access with non-temporal stores in the loop. */ mov %rdi, %r8 and $-0x80, %rdi @@ -370,8 +371,8 @@ L(gobble_256bytes_nt_loop): cmp $256, %rdx ja L(gobble_256bytes_nt_loop) sfence - vmovups %zmm4, (%rax) - vmovups %zmm5, 0x40(%rax) + vmovups %zmm4, (%r11) + vmovups %zmm5, 0x40(%r11) jmp L(check) L(preloop_large_bkw): -- cgit 1.4.1 From 58ad5f8a646338b2ee3f2136336dcf731e97ab4d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 23 May 2018 03:59:56 -0700 Subject: Add a test case for [BZ #23196] [BZ #23196] * string/test-memcpy.c (do_test1): New function. (test_main): Call it. (cherry picked from commit ed983107bbc62245b06b99f02e69acf36a0baa3e) --- ChangeLog | 6 ++++++ string/test-memcpy.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/ChangeLog b/ChangeLog index e956dd3d66..41b4dae231 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-05-23 H.J. Lu + + [BZ #23196] + * string/test-memcpy.c (do_test1): New function. + (test_main): Call it. + 2018-05-23 Andreas Schwab [BZ #23196] diff --git a/string/test-memcpy.c b/string/test-memcpy.c index 49f0a76047..dfc94b2e92 100644 --- a/string/test-memcpy.c +++ b/string/test-memcpy.c @@ -212,6 +212,50 @@ do_random_tests (void) } } +static void +do_test1 (void) +{ + size_t size = 0x100000; + void *large_buf; + + large_buf = mmap (NULL, size * 2 + page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (large_buf == MAP_FAILED) + { + puts ("Failed to allocat large_buf, skipping do_test1"); + return; + } + + if (mprotect (large_buf + size, page_size, PROT_NONE)) + error (EXIT_FAILURE, errno, "mprotect failed"); + + size_t arrary_size = size / sizeof (uint32_t); + uint32_t *dest = large_buf; + uint32_t *src = large_buf + size + page_size; + size_t i; + + for (i = 0; i < arrary_size; i++) + src[i] = (uint32_t) i; + + FOR_EACH_IMPL (impl, 0) + { + memset (dest, -1, size); + CALL (impl, (char *) dest, (char *) src, size); + for (i = 0; i < arrary_size; i++) + if (dest[i] != src[i]) + { + error (0, 0, + "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", + impl->name, dest, src, i); + ret = 1; + break; + } + } + + munmap ((void *) dest, size); + munmap ((void *) src, size); +} + int test_main (void) { @@ -253,6 +297,9 @@ test_main (void) do_test (0, 0, getpagesize ()); do_random_tests (); + + do_test1 (); + return ret; } -- cgit 1.4.1 From a5bc5ec96765ab7cf681449f194abf4aa5620423 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 24 May 2018 14:41:57 +0200 Subject: Add references to CVE-2018-11236, CVE-2017-18269 --- ChangeLog | 2 ++ NEWS | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 41b4dae231..e45fa8e6d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ 2018-05-09 Paul Pluzhnikov [BZ #22786] + CVE-2018-11236 * stdlib/canonicalize.c (__realpath): Fix overflow in path length computation. * stdlib/Makefile (test-bz22786): New test. @@ -59,6 +60,7 @@ Max Horn [BZ #22644] + CVE-2017-18269 * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed branch conditions. * string/test-memmove.c (do_test2): New testcase. diff --git a/NEWS b/NEWS index c3c6aff8fc..27548fdb4b 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,9 @@ Security related changes: for AT_SECURE or SUID binaries could be used to load libraries from the current directory. + CVE-2017-18269: An SSE2-based memmove implementation for the i386 + architecture could corrupt memory. Reported by Max Horn. + CVE-2018-1000001: Buffer underflow in realpath function when getcwd function succeeds without returning an absolute path due to unexpected behaviour of the Linux kernel getcwd syscall. Reported by halfdog. -- cgit 1.4.1 From 4df8479e6b3baf365bd4eedbba922b73471e5d73 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 24 May 2018 16:27:38 +0200 Subject: Add NEWS entry for CVE-2018-11236 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 27548fdb4b..c6c5538192 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,10 @@ Security related changes: the value of SIZE_MAX, would return a pointer to a buffer which is too small, instead of NULL. + CVE-2018-11236: Very long pathname arguments to realpath function could + result in an integer overflow and buffer overflow. Reported by Alexey + Izbyshev. + CVE-2018-11237: The mempcpy implementation for the Intel Xeon Phi architecture could write beyond the target buffer, resulting in a buffer overflow. Reported by Andreas Schwab. -- cgit 1.4.1 From 7b52c8ae05340c795654d23a0e7a2590a3e23bd2 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Fri, 1 Jun 2018 11:24:58 +0200 Subject: libio: Avoid _allocate_buffer, _free_buffer function pointers [BZ #23236] These unmangled function pointers reside on the heap and could be targeted by exploit writers, effectively bypassing libio vtable validation. Instead, we ignore these pointers and always call malloc or free. In theory, this is a backwards-incompatible change, but using the global heap instead of the user-supplied callback functions should have little application impact. (The old libstdc++ implementation exposed this functionality via a public, undocumented constructor in its strstreambuf class.) (cherry picked from commit 4e8a6346cd3da2d88bbad745a1769260d36f2783) --- ChangeLog | 24 ++++++++++++++++++++++++ NEWS | 1 + debug/vasprintf_chk.c | 4 ++-- libio/memstream.c | 4 ++-- libio/strfile.h | 11 +++++------ libio/strops.c | 14 ++++++-------- libio/vasprintf.c | 4 ++-- libio/wmemstream.c | 4 ++-- libio/wstrops.c | 16 ++++++---------- 9 files changed, 50 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index e45fa8e6d0..0126fb391b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2018-06-01 Florian Weimer + + [BZ #23236] + * libio/strfile.h (struct _IO_str_fields): Rename members to + discourage their use and add comment. + (_IO_STR_DYNAMIC): Remove unused macro. + * libio/strops.c (_IO_str_init_static_internal): Do not use + callback pointers. Call malloc and free. + (_IO_str_overflow): Do not use callback pointers. Call malloc + and free. + (enlarge_userbuf): Likewise. + (_IO_str_finish): Call free. + * libio/wstrops.c (_IO_wstr_init_static): Initialize + _allocate_buffer_unused. + (_IO_wstr_overflow): Do not use callback pointers. Call malloc + and free. + (enlarge_userbuf): Likewise. + (_IO_wstr_finish): Call free. + * debug/vasprintf_chk.c (__vasprintf_chk): Initialize + _allocate_buffer_unused, _free_buffer_unused. + * libio/memstream.c (__open_memstream): Likewise. + * libio/vasprintf.c (_IO_vasprintf): Likewise. + * libio/wmemstream.c (open_wmemstream): Likewise. + 2018-05-23 H.J. Lu [BZ #23196] diff --git a/NEWS b/NEWS index c6c5538192..b8bd101f6c 100644 --- a/NEWS +++ b/NEWS @@ -140,6 +140,7 @@ The following bugs are resolved with this release: [23037] resolv: Fully initialize struct mmsghdr in send_dg [23137] s390: Fix blocking pthread_join [23196] __mempcpy_avx512_no_vzeroupper mishandles large copies + [23236] Harden function pointers in _IO_str_fields Version 2.26 diff --git a/debug/vasprintf_chk.c b/debug/vasprintf_chk.c index 5ebfeed239..1d989dd707 100644 --- a/debug/vasprintf_chk.c +++ b/debug/vasprintf_chk.c @@ -55,8 +55,8 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format, _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; _IO_str_init_static_internal (&sf, string, init_string_size, string); sf._sbf._f._flags &= ~_IO_USER_BUF; - sf._s._allocate_buffer = (_IO_alloc_type) malloc; - sf._s._free_buffer = (_IO_free_type) free; + sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; + sf._s._free_buffer_unused = (_IO_free_type) free; /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n can only come from read-only format strings. */ diff --git a/libio/memstream.c b/libio/memstream.c index e391efd48a..c26239968d 100644 --- a/libio/memstream.c +++ b/libio/memstream.c @@ -90,8 +90,8 @@ __open_memstream (char **bufloc, _IO_size_t *sizeloc) _IO_JUMPS_FILE_plus (&new_f->fp._sf._sbf) = &_IO_mem_jumps; _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf); new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF; - new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; - new_f->fp._sf._s._free_buffer = (_IO_free_type) free; + new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; + new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; new_f->fp.bufloc = bufloc; new_f->fp.sizeloc = sizeloc; diff --git a/libio/strfile.h b/libio/strfile.h index 74bd4eb269..7ce1008516 100644 --- a/libio/strfile.h +++ b/libio/strfile.h @@ -34,8 +34,11 @@ typedef void (*_IO_free_type) (void*); struct _IO_str_fields { - _IO_alloc_type _allocate_buffer; - _IO_free_type _free_buffer; + /* These members are preserved for ABI compatibility. The glibc + implementation always calls malloc/free for user buffers if + _IO_USER_BUF or _IO_FLAGS2_USER_WBUF are not set. */ + _IO_alloc_type _allocate_buffer_unused; + _IO_free_type _free_buffer_unused; }; /* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type, @@ -55,10 +58,6 @@ typedef struct _IO_strfile_ struct _IO_str_fields _s; } _IO_strfile; -/* dynamic: set when the array object is allocated (or reallocated) as - necessary to hold a character sequence that can change in length. */ -#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0) - /* frozen: set when the program has requested that the array object not be altered, reallocated, or freed. */ #define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF) diff --git a/libio/strops.c b/libio/strops.c index d72a47c649..625c09416c 100644 --- a/libio/strops.c +++ b/libio/strops.c @@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size, fp->_IO_read_end = end; } /* A null _allocate_buffer function flags the strfile as being static. */ - sf->_s._allocate_buffer = (_IO_alloc_type) 0; + sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0; } void @@ -103,8 +103,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) _IO_size_t new_size = 2 * old_blen + 100; if (new_size < old_blen) return EOF; - new_buf - = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size); + new_buf = malloc (new_size); if (new_buf == NULL) { /* __ferror(fp) = 1; */ @@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) if (old_buf) { memcpy (new_buf, old_buf, old_blen); - (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + free (old_buf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_IO_buf_base = NULL; } @@ -182,15 +181,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) _IO_size_t newsize = offset + 100; char *oldbuf = fp->_IO_buf_base; - char *newbuf - = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize); + char *newbuf = malloc (newsize); if (newbuf == NULL) return 1; if (oldbuf != NULL) { memcpy (newbuf, oldbuf, _IO_blen (fp)); - (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); + free (oldbuf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_IO_buf_base = NULL; @@ -346,7 +344,7 @@ void _IO_str_finish (_IO_FILE *fp, int dummy) { if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) - (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); + free (fp->_IO_buf_base); fp->_IO_buf_base = NULL; _IO_default_finish (fp, 0); diff --git a/libio/vasprintf.c b/libio/vasprintf.c index a9a21545a2..50e3559ab8 100644 --- a/libio/vasprintf.c +++ b/libio/vasprintf.c @@ -54,8 +54,8 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args) _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; _IO_str_init_static_internal (&sf, string, init_string_size, string); sf._sbf._f._flags &= ~_IO_USER_BUF; - sf._s._allocate_buffer = (_IO_alloc_type) malloc; - sf._s._free_buffer = (_IO_free_type) free; + sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; + sf._s._free_buffer_unused = (_IO_free_type) free; ret = _IO_vfprintf (&sf._sbf._f, format, args); if (ret < 0) { diff --git a/libio/wmemstream.c b/libio/wmemstream.c index 103a760bf5..fdabaae6a9 100644 --- a/libio/wmemstream.c +++ b/libio/wmemstream.c @@ -92,8 +92,8 @@ open_wmemstream (wchar_t **bufloc, _IO_size_t *sizeloc) _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf, _IO_BUFSIZ / sizeof (wchar_t), buf); new_f->fp._sf._sbf._f._flags2 &= ~_IO_FLAGS2_USER_WBUF; - new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; - new_f->fp._sf._s._free_buffer = (_IO_free_type) free; + new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; + new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; new_f->fp.bufloc = bufloc; new_f->fp.sizeloc = sizeloc; diff --git a/libio/wstrops.c b/libio/wstrops.c index bb62fd6702..8f5d45a9d1 100644 --- a/libio/wstrops.c +++ b/libio/wstrops.c @@ -63,7 +63,7 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, fp->_wide_data->_IO_read_end = end; } /* A null _allocate_buffer function flags the strfile as being static. */ - (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; + (((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0; } _IO_wint_t @@ -95,9 +95,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) return EOF; - new_buf - = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size - * sizeof (wchar_t)); + new_buf = malloc (new_size * sizeof (wchar_t)); if (new_buf == NULL) { /* __ferror(fp) = 1; */ @@ -106,7 +104,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) if (old_buf) { __wmemcpy (new_buf, old_buf, old_wblen); - (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + free (old_buf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_wide_data->_IO_buf_base = NULL; } @@ -186,16 +184,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) return 1; wchar_t *oldbuf = wd->_IO_buf_base; - wchar_t *newbuf - = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize - * sizeof (wchar_t)); + wchar_t *newbuf = malloc (newsize * sizeof (wchar_t)); if (newbuf == NULL) return 1; if (oldbuf != NULL) { __wmemcpy (newbuf, oldbuf, _IO_wblen (fp)); - (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); + free (oldbuf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ wd->_IO_buf_base = NULL; @@ -357,7 +353,7 @@ void _IO_wstr_finish (_IO_FILE *fp, int dummy) { if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) - (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); + free (fp->_wide_data->_IO_buf_base); fp->_wide_data->_IO_buf_base = NULL; _IO_wdefault_finish (fp, 0); -- cgit 1.4.1 From 81b994bd8391e5994913d67b0966ce10cc0977a6 Mon Sep 17 00:00:00 2001 From: "Gabriel F. T. Gomes" Date: Mon, 14 May 2018 09:04:28 -0300 Subject: Fix parameter type in C++ version of iseqsig (bug 23171) The commit commit c85e54ac6cef0faed7b7ffc722f52523dec59bf5 Author: Gabriel F. T. Gomes Date: Fri Nov 3 10:44:36 2017 -0200 Provide a C++ version of iseqsig (bug 22377) mistakenly used double parameters in the long double version of iseqsig, thus causing spurious conversions to double, as reported on bug 23171. Tested for powerpc64le and x86_64. (cherry picked from commit fb0e10b8eb1ebb68c57d4551f7a95118f3c54837) --- ChangeLog | 6 ++++++ NEWS | 1 + math/math.h | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0126fb391b..9c6a1b97bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-05-24 Gabriel F. T. Gomes + + [BZ #23171] + * math/math.h [C++] (iseqsig): Fix parameter type for the long + double version. + 2018-06-01 Florian Weimer [BZ #23236] diff --git a/NEWS b/NEWS index b8bd101f6c..c323323259 100644 --- a/NEWS +++ b/NEWS @@ -139,6 +139,7 @@ The following bugs are resolved with this release: [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg [23137] s390: Fix blocking pthread_join + [23171] Fix parameter type in C++ version of iseqsig [23196] __mempcpy_avx512_no_vzeroupper mishandles large copies [23236] Harden function pointers in _IO_str_fields diff --git a/math/math.h b/math/math.h index 5a282b8c6b..4c30306d58 100644 --- a/math/math.h +++ b/math/math.h @@ -880,7 +880,7 @@ template<> struct __iseqsig_type template<> struct __iseqsig_type { - static int __call (double __x, double __y) throw () + static int __call (long double __x, long double __y) throw () { # ifndef __NO_LONG_DOUBLE_MATH return __iseqsigl (__x, __y); -- cgit 1.4.1 From f958b45d528390fb486cecd0b0615a1994e96795 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 28 Jun 2018 13:22:34 +0200 Subject: Use _STRUCT_TIMESPEC as guard in [BZ #23349] After commit d76d3703551a362b472c866b5b6089f66f8daa8e ("Fix missing timespec definition for sys/stat.h (BZ #21371)") in combination with kernel UAPI changes, GCC sanitizer builds start to fail due to a conflicting definition of struct timespec in . Use _STRUCT_TIMESPEC as the header file inclusion guard, which is already checked in the kernel header, to support including and in the same translation unit. (cherry picked from commit c1c2848b572ea7f92b7fa81dd5b1b9ef7c69b83b) --- ChangeLog | 6 ++++++ NEWS | 1 + time/bits/types/struct_timespec.h | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9c6a1b97bd..0981fcaf71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-06-28 Florian Weimer + + [BZ #23349] + * time/bits/types/struct_timespec.h: Change header inclusion guard to + _STRUCT_TIMESPEC. + 2018-05-24 Gabriel F. T. Gomes [BZ #23171] diff --git a/NEWS b/NEWS index c323323259..c34c6393ee 100644 --- a/NEWS +++ b/NEWS @@ -142,6 +142,7 @@ The following bugs are resolved with this release: [23171] Fix parameter type in C++ version of iseqsig [23196] __mempcpy_avx512_no_vzeroupper mishandles large copies [23236] Harden function pointers in _IO_str_fields + [23349] Various glibc headers no longer compatible with Version 2.26 diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h index 644db9fdb6..5b77c52b4f 100644 --- a/time/bits/types/struct_timespec.h +++ b/time/bits/types/struct_timespec.h @@ -1,5 +1,6 @@ -#ifndef __timespec_defined -#define __timespec_defined 1 +/* NB: Include guard matches what uses. */ +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC 1 #include -- cgit 1.4.1 From 3aaf8bda00988f21f4a83affff47bafc74a745a0 Mon Sep 17 00:00:00 2001 From: Daniel Alvarez Date: Fri, 29 Jun 2018 17:23:13 +0200 Subject: getifaddrs: Don't return ifa entries with NULL names [BZ #21812] A lookup operation in map_newlink could turn into an insert because of holes in the interface part of the map. This leads to incorrectly set the name of the interface to NULL when the interface is not present for the address being processed (most likely because the interface was added between the RTM_GETLINK and RTM_GETADDR calls to the kernel). When such changes are detected by the kernel, it'll mark the dump as "inconsistent" by setting NLM_F_DUMP_INTR flag on the next netlink message. This patch checks this condition and retries the whole operation. Hopes are that next time the interface corresponding to the address entry is present in the list and correct name is returned. (cherry picked from commit c1f86a33ca32e26a9d6e29fc961e5ecb5e2e5eb4) --- ChangeLog | 7 +++++++ NEWS | 1 + sysdeps/unix/sysv/linux/ifaddrs.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0981fcaf71..c502aceddb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2018-06-29 Daniel Alvarez + Jakub Sitnicki + + [BZ #21812] + * sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs_internal): Retry + on NLM_F_DUMP_INTR. + 2018-06-28 Florian Weimer [BZ #23349] diff --git a/NEWS b/NEWS index c34c6393ee..db43d87ee0 100644 --- a/NEWS +++ b/NEWS @@ -93,6 +93,7 @@ The following bugs are resolved with this release: [21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve [21269] i386 sigaction sa_restorer handling is wrong [21780] posix: Set p{read,write}v2 to return ENOTSUP + [21812] getifaddrs: Don't return ifa entries with NULL names [21871] x86-64: Use _dl_runtime_resolve_opt only with AVX512F [21885] getaddrinfo: Release resolver context on error in gethosts [21915] getaddrinfo: incorrect result handling for NSS service modules diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c index 3bc9902863..4f75401850 100644 --- a/sysdeps/unix/sysv/linux/ifaddrs.c +++ b/sysdeps/unix/sysv/linux/ifaddrs.c @@ -371,6 +371,14 @@ getifaddrs_internal (struct ifaddrs **ifap) if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) continue; + /* If the dump got interrupted, we can't rely on the results + so try again. */ + if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) + { + result = -EAGAIN; + goto exit_free; + } + if (nlh->nlmsg_type == NLMSG_DONE) break; /* ok */ -- cgit 1.4.1 From 74d16a57a3615fcf05e5c60cb5a8f25e8acf38b9 Mon Sep 17 00:00:00 2001 From: Steve Ellcey Date: Fri, 29 Jun 2018 17:32:23 +0200 Subject: Check length of ifname before copying it into to ifreq structure. [BZ #22442] * sysdeps/unix/sysv/linux/if_index.c (__if_nametoindex): Check if ifname is too long. (cherry picked from commit 2180fee114b778515b3f560e5ff1e795282e60b0) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/unix/sysv/linux/if_index.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index c502aceddb..7ecc33e61d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-11-15 Steve Ellcey + + [BZ #22442] + * sysdeps/unix/sysv/linux/if_index.c (__if_nametoindex): + Check if ifname is too long. + 2018-06-29 Daniel Alvarez Jakub Sitnicki diff --git a/NEWS b/NEWS index db43d87ee0..48d28e166a 100644 --- a/NEWS +++ b/NEWS @@ -120,6 +120,7 @@ The following bugs are resolved with this release: [22299] x86-64: Don't set GLRO(dl_platform) to NULL [22320] glob: Fix one-byte overflow (CVE-2017-15670) [22321] sysconf: Fix missing definition of UIO_MAXIOV on Linux + [22442] if_nametoindex: Check length of ifname before copying it [22322] libc: [mips64] wrong bits/long-double.h installed [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671) [22342] NSCD not properly caching netgroup diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index 8ba5eae781..a874634d52 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -43,6 +43,12 @@ __if_nametoindex (const char *ifname) if (fd < 0) return 0; + if (strlen (ifname) >= IFNAMSIZ) + { + __set_errno (ENODEV); + return 0; + } + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) { -- cgit 1.4.1 From 2781bd5a8690b5f1553b655f947a35f1d3dd23d0 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 26 Jun 2018 10:24:52 +0200 Subject: libio: Disable vtable validation in case of interposition [BZ #23313] (cherry picked from commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0) --- ChangeLog | 5 +++++ NEWS | 1 + libio/vtables.c | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7ecc33e61d..f1880ebc37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-06-26 Florian Weimer + + [BZ #23313] + * libio/vtables.c (check_stdfiles_vtables): New ELF constructor. + 2017-11-15 Steve Ellcey [BZ #22442] diff --git a/NEWS b/NEWS index 48d28e166a..5bcca538c6 100644 --- a/NEWS +++ b/NEWS @@ -144,6 +144,7 @@ The following bugs are resolved with this release: [23171] Fix parameter type in C++ version of iseqsig [23196] __mempcpy_avx512_no_vzeroupper mishandles large copies [23236] Harden function pointers in _IO_str_fields + [23313] libio: Disable vtable validation in case of interposition [23349] Various glibc headers no longer compatible with Version 2.26 diff --git a/libio/vtables.c b/libio/vtables.c index 41b48db98c..a11226ab17 100644 --- a/libio/vtables.c +++ b/libio/vtables.c @@ -70,3 +70,19 @@ _IO_vtable_check (void) __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n"); } + +/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and + install their own vtables directly, without calling _IO_init or + other functions. Detect this by looking at the vtables values + during startup, and disable vtable validation in this case. */ +#ifdef SHARED +__attribute__ ((constructor)) +static void +check_stdfiles_vtables (void) +{ + if (_IO_2_1_stdin_.vtable != &_IO_file_jumps + || _IO_2_1_stdout_.vtable != &_IO_file_jumps + || _IO_2_1_stderr_.vtable != &_IO_file_jumps) + IO_set_accept_foreign_vtables (&_IO_vtable_check); +} +#endif -- cgit 1.4.1 From 762e9d63d531de78c930335dd3afbc593046514b Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 3 Jul 2018 15:58:48 +0200 Subject: NEWS: Reorder out-of-order bugs --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 5bcca538c6..c0b9398e83 100644 --- a/NEWS +++ b/NEWS @@ -120,23 +120,23 @@ The following bugs are resolved with this release: [22299] x86-64: Don't set GLRO(dl_platform) to NULL [22320] glob: Fix one-byte overflow (CVE-2017-15670) [22321] sysconf: Fix missing definition of UIO_MAXIOV on Linux - [22442] if_nametoindex: Check length of ifname before copying it [22322] libc: [mips64] wrong bits/long-double.h installed [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671) [22342] NSCD not properly caching netgroup [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485) [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) [22377] Provide a C++ version of iseqsig - [22636] PTHREAD_STACK_MIN is too small on x86-64 + [22442] if_nametoindex: Check length of ifname before copying it [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice + [22636] PTHREAD_STACK_MIN is too small on x86-64 [22637] nptl: Fix stack guard size accounting [22644] Fix i386 memmove issue [22679] getcwd(3) can succeed without returning an absolute path (CVE-2018-1000001) [22685] powerpc: Fix syscalls during early process initialization - [22786] Fix path length overflow in realpath [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE [22774] malloc: Integer overflow in malloc (CVE-2018-6551) + [22786] Fix path length overflow in realpath [23005] resolv: Fix crash in resolver on memory allocation failure [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg -- cgit 1.4.1 From 4b10e69b1f50dc0afbc647ec3c4c8f79cf75ca96 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 3 Jul 2018 18:13:05 +0200 Subject: Synchronize support/ infrastructure with master This commit updates the support/ subdirectory to commit 5c0202af4b3d588c04bcec7baf05706b21cd7416 on the master branch. --- support/Makefile | 8 ++ support/check.h | 22 ++++++ support/support.h | 6 ++ support/support_format_addrinfo.c | 8 +- support/support_openpty.c | 109 ++++++++++++++++++++++++++ support/support_quote_blob.c | 83 ++++++++++++++++++++ support/support_test_compare_blob.c | 76 ++++++++++++++++++ support/support_test_main.c | 3 +- support/test-driver.c | 4 + support/test-driver.h | 1 + support/tst-support_quote_blob.c | 61 +++++++++++++++ support/tst-test_compare_blob.c | 125 ++++++++++++++++++++++++++++++ support/tty.h | 45 +++++++++++ support/xpthread_barrierattr_destroy.c | 26 +++++++ support/xpthread_barrierattr_init.c | 26 +++++++ support/xpthread_barrierattr_setpshared.c | 26 +++++++ support/xthread.h | 3 + 17 files changed, 628 insertions(+), 4 deletions(-) create mode 100644 support/support_openpty.c create mode 100644 support/support_quote_blob.c create mode 100644 support/support_test_compare_blob.c create mode 100644 support/tst-support_quote_blob.c create mode 100644 support/tst-test_compare_blob.c create mode 100644 support/tty.h create mode 100644 support/xpthread_barrierattr_destroy.c create mode 100644 support/xpthread_barrierattr_init.c create mode 100644 support/xpthread_barrierattr_setpshared.c diff --git a/support/Makefile b/support/Makefile index 1bda81e55e..652d2cdf69 100644 --- a/support/Makefile +++ b/support/Makefile @@ -52,9 +52,12 @@ libsupport-routines = \ support_format_hostent \ support_format_netent \ support_isolate_in_subprocess \ + support_openpty \ + support_quote_blob \ support_record_failure \ support_run_diff \ support_shared_allocate \ + support_test_compare_blob \ support_test_compare_failure \ support_write_file_string \ support_test_main \ @@ -95,6 +98,9 @@ libsupport-routines = \ xpthread_barrier_destroy \ xpthread_barrier_init \ xpthread_barrier_wait \ + xpthread_barrierattr_destroy \ + xpthread_barrierattr_init \ + xpthread_barrierattr_setpshared \ xpthread_cancel \ xpthread_check_return \ xpthread_cond_wait \ @@ -150,8 +156,10 @@ tests = \ tst-support-namespace \ tst-support_capture_subprocess \ tst-support_format_dns_packet \ + tst-support_quote_blob \ tst-support_record_failure \ tst-test_compare \ + tst-test_compare_blob \ tst-xreadlink \ ifeq ($(run-built-tests),yes) diff --git a/support/check.h b/support/check.h index 2192f38941..b3a4645e92 100644 --- a/support/check.h +++ b/support/check.h @@ -64,6 +64,8 @@ __BEGIN_DECLS (1, __FILE__, __LINE__, #expr); \ }) + + int support_print_failure_impl (const char *file, int line, const char *format, ...) __attribute__ ((nonnull (1), format (printf, 3, 4))); @@ -141,6 +143,26 @@ void support_test_compare_failure (const char *file, int line, int right_size); +/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT + + RIGHT_LENGTH) and report a test failure if the arrays are + different. LEFT_LENGTH and RIGHT_LENGTH are measured in bytes. If + the length is null, the corresponding pointer is ignored (i.e., it + can be NULL). The blobs should be reasonably short because on + mismatch, both are printed. */ +#define TEST_COMPARE_BLOB(left, left_length, right, right_length) \ + (support_test_compare_blob (left, left_length, right, right_length, \ + __FILE__, __LINE__, \ + #left, #left_length, #right, #right_length)) + +void support_test_compare_blob (const void *left, + unsigned long int left_length, + const void *right, + unsigned long int right_length, + const char *file, int line, + const char *left_exp, const char *left_len_exp, + const char *right_exp, + const char *right_len_exp); + /* Internal function called by the test driver. */ int support_report_failure (int status) __attribute__ ((weak, warn_unused_result)); diff --git a/support/support.h b/support/support.h index bc5827ed87..b61fe0735c 100644 --- a/support/support.h +++ b/support/support.h @@ -59,6 +59,12 @@ void support_shared_free (void *); process on error. */ void support_write_file_string (const char *path, const char *contents); +/* Quote the contents of the byte array starting at BLOB, of LENGTH + bytes, in such a way that the result string can be included in a C + literal (in single/double quotes, without putting the quotes into + the result). */ +char *support_quote_blob (const void *blob, size_t length); + /* Error-checking wrapper functions which terminate the process on error. */ diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c index c5e00e516a..60d2cc40f6 100644 --- a/support/support_format_addrinfo.c +++ b/support/support_format_addrinfo.c @@ -67,8 +67,6 @@ format_ai_flags (FILE *out, struct addrinfo *ai) FLAG (AI_ADDRCONFIG); FLAG (AI_IDN); FLAG (AI_CANONIDN); - FLAG (AI_IDN_ALLOW_UNASSIGNED); - FLAG (AI_IDN_USE_STD3_ASCII_RULES); FLAG (AI_NUMERICSERV); #undef FLAG int remaining = ai->ai_flags & ~flags_printed; @@ -220,7 +218,11 @@ support_format_addrinfo (struct addrinfo *ai, int ret) xopen_memstream (&mem); if (ret != 0) { - fprintf (mem.out, "error: %s\n", gai_strerror (ret)); + const char *errmsg = gai_strerror (ret); + if (strcmp (errmsg, "Unknown error") == 0) + fprintf (mem.out, "error: Unknown error %d\n", ret); + else + fprintf (mem.out, "error: %s\n", errmsg); if (ret == EAI_SYSTEM) { errno = errno_copy; diff --git a/support/support_openpty.c b/support/support_openpty.c new file mode 100644 index 0000000000..ac779ab91e --- /dev/null +++ b/support/support_openpty.c @@ -0,0 +1,109 @@ +/* Open a pseudoterminal. + 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 + . */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* As ptsname, but allocates space for an appropriately-sized string + using malloc. */ +static char * +xptsname (int fd) +{ + int rv; + size_t buf_len = 128; + char *buf = xmalloc (buf_len); + for (;;) + { + rv = ptsname_r (fd, buf, buf_len); + if (rv) + FAIL_EXIT1 ("ptsname_r: %s", strerror (errno)); + + if (memchr (buf, '\0', buf_len)) + return buf; /* ptsname succeeded and the buffer was not truncated */ + + buf_len *= 2; + buf = xrealloc (buf, buf_len); + } +} + +void +support_openpty (int *a_outer, int *a_inner, char **a_name, + const struct termios *termp, + const struct winsize *winp) +{ + int outer = -1, inner = -1; + char *namebuf = 0; + + outer = posix_openpt (O_RDWR | O_NOCTTY); + if (outer == -1) + FAIL_EXIT1 ("posix_openpt: %s", strerror (errno)); + + if (grantpt (outer)) + FAIL_EXIT1 ("grantpt: %s", strerror (errno)); + + if (unlockpt (outer)) + FAIL_EXIT1 ("unlockpt: %s", strerror (errno)); + + +#ifdef TIOCGPTPEER + inner = ioctl (outer, TIOCGPTPEER, O_RDWR | O_NOCTTY); +#endif + if (inner == -1) + { + /* The kernel might not support TIOCGPTPEER, fall back to open + by name. */ + namebuf = xptsname (outer); + inner = open (namebuf, O_RDWR | O_NOCTTY); + if (inner == -1) + FAIL_EXIT1 ("%s: %s", namebuf, strerror (errno)); + } + + if (termp) + { + if (tcsetattr (inner, TCSAFLUSH, termp)) + FAIL_EXIT1 ("tcsetattr: %s", strerror (errno)); + } +#ifdef TIOCSWINSZ + if (winp) + { + if (ioctl (inner, TIOCSWINSZ, winp)) + FAIL_EXIT1 ("TIOCSWINSZ: %s", strerror (errno)); + } +#endif + + if (a_name) + { + if (!namebuf) + namebuf = xptsname (outer); + *a_name = namebuf; + } + else + free (namebuf); + *a_outer = outer; + *a_inner = inner; +} diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c new file mode 100644 index 0000000000..d6a678d8d6 --- /dev/null +++ b/support/support_quote_blob.c @@ -0,0 +1,83 @@ +/* Quote a blob so that it can be used in C literals. + 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 + . */ + +#include +#include + +char * +support_quote_blob (const void *blob, size_t length) +{ + struct xmemstream out; + xopen_memstream (&out); + + const unsigned char *p = blob; + for (size_t i = 0; i < length; ++i) + { + unsigned char ch = p[i]; + + /* Use C backslash escapes for those control characters for + which they are defined. */ + switch (ch) + { + case '\a': + putc_unlocked ('\\', out.out); + putc_unlocked ('a', out.out); + break; + case '\b': + putc_unlocked ('\\', out.out); + putc_unlocked ('b', out.out); + break; + case '\f': + putc_unlocked ('\\', out.out); + putc_unlocked ('f', out.out); + break; + case '\n': + putc_unlocked ('\\', out.out); + putc_unlocked ('n', out.out); + break; + case '\r': + putc_unlocked ('\\', out.out); + putc_unlocked ('r', out.out); + break; + case '\t': + putc_unlocked ('\\', out.out); + putc_unlocked ('t', out.out); + break; + case '\v': + putc_unlocked ('\\', out.out); + putc_unlocked ('v', out.out); + break; + case '\\': + case '\'': + case '\"': + putc_unlocked ('\\', out.out); + putc_unlocked (ch, out.out); + break; + default: + if (ch < ' ' || ch > '~') + /* Use octal sequences because they are fixed width, + unlike hexadecimal sequences. */ + fprintf (out.out, "\\%03o", ch); + else + putc_unlocked (ch, out.out); + } + } + + xfclose_memstream (&out); + return out.buffer; +} diff --git a/support/support_test_compare_blob.c b/support/support_test_compare_blob.c new file mode 100644 index 0000000000..c5e63d1b93 --- /dev/null +++ b/support/support_test_compare_blob.c @@ -0,0 +1,76 @@ +/* Check two binary blobs for equality. + 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 + . */ + +#include +#include +#include +#include +#include +#include + +static void +report_length (const char *what, unsigned long int length, const char *expr) +{ + printf (" %s %lu bytes (from %s)\n", what, length, expr); +} + +static void +report_blob (const char *what, const unsigned char *blob, + unsigned long int length, const char *expr) +{ + if (length > 0) + { + printf (" %s (evaluated from %s):\n", what, expr); + char *quoted = support_quote_blob (blob, length); + printf (" \"%s\"\n", quoted); + free (quoted); + + fputs (" ", stdout); + for (unsigned long i = 0; i < length; ++i) + printf (" %02X", blob[i]); + putc ('\n', stdout); + } +} + +void +support_test_compare_blob (const void *left, unsigned long int left_length, + const void *right, unsigned long int right_length, + const char *file, int line, + const char *left_expr, const char *left_len_expr, + const char *right_expr, const char *right_len_expr) +{ + /* No differences are possible if both lengths are null. */ + if (left_length == 0 && right_length == 0) + return; + + if (left_length != right_length || left == NULL || right == NULL + || memcmp (left, right, left_length) != 0) + { + support_record_failure (); + printf ("%s:%d: error: blob comparison failed\n", file, line); + if (left_length == right_length) + printf (" blob length: %lu bytes\n", left_length); + else + { + report_length ("left length: ", left_length, left_len_expr); + report_length ("right length:", right_length, right_len_expr); + } + report_blob ("left", left, left_length, left_expr); + report_blob ("right", right, right_length, right_expr); + } +} diff --git a/support/support_test_main.c b/support/support_test_main.c index 396385729b..23429779ac 100644 --- a/support/support_test_main.c +++ b/support/support_test_main.c @@ -270,7 +270,8 @@ support_test_main (int argc, char **argv, const struct test_config *config) timeout = DEFAULT_TIMEOUT; /* Make sure we see all message, even those on stdout. */ - setvbuf (stdout, NULL, _IONBF, 0); + if (!config->no_setvbuf) + setvbuf (stdout, NULL, _IONBF, 0); /* Make sure temporary files are deleted. */ if (support_delete_temp_files != NULL) diff --git a/support/test-driver.c b/support/test-driver.c index 09c8783e4f..9798f16227 100644 --- a/support/test-driver.c +++ b/support/test-driver.c @@ -140,6 +140,10 @@ main (int argc, char **argv) test_config.no_mallopt = 1; #endif +#ifdef TEST_NO_SETVBUF + test_config.no_setvbuf = 1; +#endif + #ifdef TIMEOUT test_config.timeout = TIMEOUT; #endif diff --git a/support/test-driver.h b/support/test-driver.h index 1708d68d60..549179b254 100644 --- a/support/test-driver.h +++ b/support/test-driver.h @@ -35,6 +35,7 @@ struct test_config int expected_status; /* Expected exit status. */ int expected_signal; /* If non-zero, expect termination by signal. */ char no_mallopt; /* Boolean flag to disable mallopt. */ + char no_setvbuf; /* Boolean flag to disable setvbuf. */ const char *optstring; /* Short command line options. */ }; diff --git a/support/tst-support_quote_blob.c b/support/tst-support_quote_blob.c new file mode 100644 index 0000000000..5467a190a6 --- /dev/null +++ b/support/tst-support_quote_blob.c @@ -0,0 +1,61 @@ +/* Test the support_quote_blob function. + 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 + . */ + +#include +#include +#include +#include + +static int +do_test (void) +{ + /* Check handling of the empty blob, both with and without trailing + NUL byte. */ + char *p = support_quote_blob ("", 0); + TEST_COMPARE (strlen (p), 0); + free (p); + p = support_quote_blob ("X", 0); + TEST_COMPARE (strlen (p), 0); + free (p); + + /* Check escaping of backslash-escaped characters, and lack of + escaping for other shell meta-characters. */ + p = support_quote_blob ("$()*?`@[]{}~\'\"X", 14); + TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0); + free (p); + + /* Check lack of escaping for letters and digits. */ +#define LETTERS_AND_DIGTS \ + "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "0123456789" + p = support_quote_blob (LETTERS_AND_DIGTS "@", 2 * 26 + 10); + TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0); + free (p); + + /* Check escaping of control characters and other non-printable + characters. */ + p = support_quote_blob ("\r\n\t\a\b\f\v\1\177\200\377\0@", 14); + TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" + "\\177\\200\\377\\000@\\000"), 0); + free (p); + + return 0; +} + +#include diff --git a/support/tst-test_compare_blob.c b/support/tst-test_compare_blob.c new file mode 100644 index 0000000000..aa8643e182 --- /dev/null +++ b/support/tst-test_compare_blob.c @@ -0,0 +1,125 @@ +/* Basic test for the TEST_COMPARE_BLOB macro. + 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 + . */ + +#include +#include +#include + +static void +subprocess (void *closure) +{ + /* These tests should fail. They were chosen to cover differences + in length (with the same contents), single-bit mismatches, and + mismatching null pointers. */ + TEST_COMPARE_BLOB ("", 0, "", 1); /* Line 29. */ + TEST_COMPARE_BLOB ("X", 1, "", 1); /* Line 30. */ + TEST_COMPARE_BLOB ("abcd", 3, "abcd", 4); /* Line 31. */ + TEST_COMPARE_BLOB ("abcd", 4, "abcD", 4); /* Line 32. */ + TEST_COMPARE_BLOB ("abcd", 4, NULL, 0); /* Line 33. */ + TEST_COMPARE_BLOB (NULL, 0, "abcd", 4); /* Line 34. */ +} + +/* Same contents, different addresses. */ +char buffer_abc_1[] = "abc"; +char buffer_abc_2[] = "abc"; + +static int +do_test (void) +{ + /* This should succeed. Even if the pointers and array contents are + different, zero-length inputs are not different. */ + TEST_COMPARE_BLOB ("", 0, "", 0); + TEST_COMPARE_BLOB ("", 0, buffer_abc_1, 0); + TEST_COMPARE_BLOB (buffer_abc_1, 0, "", 0); + TEST_COMPARE_BLOB (NULL, 0, "", 0); + TEST_COMPARE_BLOB ("", 0, NULL, 0); + TEST_COMPARE_BLOB (NULL, 0, NULL, 0); + + /* Check equality of blobs containing a single NUL byte. */ + TEST_COMPARE_BLOB ("", 1, "", 1); + TEST_COMPARE_BLOB ("", 1, &buffer_abc_1[3], 1); + + /* Check equality of blobs of varying lengths. */ + for (size_t i = 0; i <= sizeof (buffer_abc_1); ++i) + TEST_COMPARE_BLOB (buffer_abc_1, i, buffer_abc_2, i); + + struct support_capture_subprocess proc = support_capture_subprocess + (&subprocess, NULL); + + /* Discard the reported error. */ + support_record_failure_reset (); + + puts ("info: *** subprocess output starts ***"); + fputs (proc.out.buffer, stdout); + puts ("info: *** subprocess output ends ***"); + + TEST_VERIFY + (strcmp (proc.out.buffer, +"tst-test_compare_blob.c:29: error: blob comparison failed\n" +" left length: 0 bytes (from 0)\n" +" right length: 1 bytes (from 1)\n" +" right (evaluated from \"\"):\n" +" \"\\000\"\n" +" 00\n" +"tst-test_compare_blob.c:30: error: blob comparison failed\n" +" blob length: 1 bytes\n" +" left (evaluated from \"X\"):\n" +" \"X\"\n" +" 58\n" +" right (evaluated from \"\"):\n" +" \"\\000\"\n" +" 00\n" +"tst-test_compare_blob.c:31: error: blob comparison failed\n" +" left length: 3 bytes (from 3)\n" +" right length: 4 bytes (from 4)\n" +" left (evaluated from \"abcd\"):\n" +" \"abc\"\n" +" 61 62 63\n" +" right (evaluated from \"abcd\"):\n" +" \"abcd\"\n" +" 61 62 63 64\n" +"tst-test_compare_blob.c:32: error: blob comparison failed\n" +" blob length: 4 bytes\n" +" left (evaluated from \"abcd\"):\n" +" \"abcd\"\n" +" 61 62 63 64\n" +" right (evaluated from \"abcD\"):\n" +" \"abcD\"\n" +" 61 62 63 44\n" +"tst-test_compare_blob.c:33: error: blob comparison failed\n" +" left length: 4 bytes (from 4)\n" +" right length: 0 bytes (from 0)\n" +" left (evaluated from \"abcd\"):\n" +" \"abcd\"\n" +" 61 62 63 64\n" +"tst-test_compare_blob.c:34: error: blob comparison failed\n" +" left length: 0 bytes (from 0)\n" +" right length: 4 bytes (from 4)\n" +" right (evaluated from \"abcd\"):\n" +" \"abcd\"\n" +" 61 62 63 64\n" + ) == 0); + + /* Check that there is no output on standard error. */ + support_capture_subprocess_check (&proc, "TEST_COMPARE_BLOB", + 0, sc_allow_stdout); + + return 0; +} + +#include diff --git a/support/tty.h b/support/tty.h new file mode 100644 index 0000000000..1d37c42279 --- /dev/null +++ b/support/tty.h @@ -0,0 +1,45 @@ +/* Support functions related to (pseudo)terminals. + 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 + . */ + +#ifndef _SUPPORT_TTY_H +#define _SUPPORT_TTY_H 1 + +struct termios; +struct winsize; + +/** Open a pseudoterminal pair. The outer fd is written to the address + A_OUTER and the inner fd to A_INNER. + + If A_NAME is not NULL, it will be set to point to a string naming + the /dev/pts/NNN device corresponding to the inner fd; space for + this string is allocated with malloc and should be freed by the + caller when no longer needed. (This is different from the libutil + function 'openpty'.) + + If TERMP is not NULL, the terminal parameters will be initialized + according to the termios structure it points to. + + If WINP is not NULL, the terminal window size will be set + accordingly. + + Terminates the process on failure (like xmalloc). */ +extern void support_openpty (int *a_outer, int *a_inner, char **a_name, + const struct termios *termp, + const struct winsize *winp); + +#endif diff --git a/support/xpthread_barrierattr_destroy.c b/support/xpthread_barrierattr_destroy.c new file mode 100644 index 0000000000..3e471f9a81 --- /dev/null +++ b/support/xpthread_barrierattr_destroy.c @@ -0,0 +1,26 @@ +/* pthread_barrierattr_destroy with error checking. + 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 + . */ + +#include + +void +xpthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + xpthread_check_return ("pthread_barrierattr_destroy", + pthread_barrierattr_destroy (attr)); +} diff --git a/support/xpthread_barrierattr_init.c b/support/xpthread_barrierattr_init.c new file mode 100644 index 0000000000..4ee14e78f3 --- /dev/null +++ b/support/xpthread_barrierattr_init.c @@ -0,0 +1,26 @@ +/* pthread_barrierattr_init with error checking. + 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 + . */ + +#include + +void +xpthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + xpthread_check_return ("pthread_barrierattr_init", + pthread_barrierattr_init (attr)); +} diff --git a/support/xpthread_barrierattr_setpshared.c b/support/xpthread_barrierattr_setpshared.c new file mode 100644 index 0000000000..90b2c5bec6 --- /dev/null +++ b/support/xpthread_barrierattr_setpshared.c @@ -0,0 +1,26 @@ +/* pthread_barrierattr_setpshared with error checking. + 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 + . */ + +#include + +void +xpthread_barrierattr_setpshared (pthread_barrierattr_t *attr, int pshared) +{ + xpthread_check_return ("pthread_barrierattr_setpshared", + pthread_barrierattr_setpshared (attr, pshared)); +} diff --git a/support/xthread.h b/support/xthread.h index 79358e7c99..623f5ad0ac 100644 --- a/support/xthread.h +++ b/support/xthread.h @@ -41,6 +41,9 @@ void xpthread_check_return (const char *function, int value); void xpthread_barrier_init (pthread_barrier_t *barrier, pthread_barrierattr_t *attr, unsigned int count); void xpthread_barrier_destroy (pthread_barrier_t *barrier); +void xpthread_barrierattr_destroy (pthread_barrierattr_t *); +void xpthread_barrierattr_init (pthread_barrierattr_t *); +void xpthread_barrierattr_setpshared (pthread_barrierattr_t *, int pshared); void xpthread_mutexattr_destroy (pthread_mutexattr_t *); void xpthread_mutexattr_init (pthread_mutexattr_t *); void xpthread_mutexattr_setprotocol (pthread_mutexattr_t *, int); -- cgit 1.4.1 From 20dc7a909ab1f4848fb961e94f61bbbe3f72a3bf Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 3 Jul 2018 17:57:14 +0200 Subject: libio: Add tst-vtables, tst-vtables-interposed (cherry picked from commit 29055464a03c72762969a2e8734d0d05d4d70e58) Some adjustments were needed for a tricky multi-inclusion issue related to libioP.h. --- ChangeLog | 8 + libio/Makefile | 3 + libio/tst-vtables-common.c | 511 +++++++++++++++++++++++++++++++++++++++++ libio/tst-vtables-interposed.c | 37 +++ libio/tst-vtables.c | 29 +++ 5 files changed, 588 insertions(+) create mode 100644 libio/tst-vtables-common.c create mode 100644 libio/tst-vtables-interposed.c create mode 100644 libio/tst-vtables.c diff --git a/ChangeLog b/ChangeLog index f1880ebc37..7a700da223 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-06-26 Florian Weimer + + * libio/Makefile (tests-internal): Add tst-vtables, + tst-vtables-interposed. + * libio/tst-vtables.c: New file. + * libio/tst-vtables-common.c: Likewise. + * libio/tst-vtables-interposed.c: Likewise. + 2018-06-26 Florian Weimer [BZ #23313] diff --git a/libio/Makefile b/libio/Makefile index a002a3365c..74bf5279f1 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -63,6 +63,9 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ tst-ftell-append tst-fputws + +tests-internal = tst-vtables tst-vtables-interposed + ifeq (yes,$(build-shared)) # Add test-fopenloc only if shared library is enabled since it depends on # shared localedata objects. diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c new file mode 100644 index 0000000000..dc8d89c195 --- /dev/null +++ b/libio/tst-vtables-common.c @@ -0,0 +1,511 @@ +/* Test for libio vtables and their validation. Common code. + 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 + . */ + +/* This test provides some coverage for how various stdio functions + use the vtables in FILE * objects. The focus is mostly on which + functions call which methods, not so much on validating data + processing. An initial series of tests check that custom vtables + do not work without activation through _IO_init. + + Note: libio vtables are deprecated feature. Do not use this test + as a documentation source for writing custom vtables. See + fopencookie for a different way of creating custom stdio + streams. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Data shared between the test subprocess and the test driver in the + parent. Note that *shared is reset at the start of the check_call + function. */ +struct shared +{ + /* Expected file pointer for method calls. */ + FILE *fp; + + /* If true, assume that a call to _IO_init is needed to enable + custom vtables. */ + bool initially_disabled; + + /* Requested return value for the methods which have one. */ + int return_value; + + /* A value (usually a character) recorded by some of the methods + below. */ + int value; + + /* Likewise, for some data. */ + char buffer[16]; + size_t buffer_length; + + /* Total number of method calls. */ + unsigned int calls; + + /* Individual method call counts. */ + unsigned int calls_finish; + unsigned int calls_overflow; + unsigned int calls_underflow; + unsigned int calls_uflow; + unsigned int calls_pbackfail; + unsigned int calls_xsputn; + unsigned int calls_xsgetn; + unsigned int calls_seekoff; + unsigned int calls_seekpos; + unsigned int calls_setbuf; + unsigned int calls_sync; + unsigned int calls_doallocate; + unsigned int calls_read; + unsigned int calls_write; + unsigned int calls_seek; + unsigned int calls_close; + unsigned int calls_stat; + unsigned int calls_showmanyc; + unsigned int calls_imbue; +} *shared; + +/* Method implementations which increment the counters in *shared. */ + +static void +log_method (FILE *fp, const char *name) +{ + if (test_verbose > 0) + printf ("info: %s (%p) called\n", name, fp); +} + +static void +method_finish (FILE *fp, int dummy) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_finish; +} + +static int +method_overflow (FILE *fp, int ch) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_overflow; + shared->value = ch; + return shared->return_value; +} + +static int +method_underflow (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_underflow; + return shared->return_value; +} + +static int +method_uflow (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_uflow; + return shared->return_value; +} + +static int +method_pbackfail (FILE *fp, int ch) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_pbackfail; + shared->value = ch; + return shared->return_value; +} + +static size_t +method_xsputn (FILE *fp, const void *data, size_t n) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_xsputn; + + size_t to_copy = n; + if (n > sizeof (shared->buffer)) + to_copy = sizeof (shared->buffer); + memcpy (shared->buffer, data, to_copy); + shared->buffer_length = to_copy; + return to_copy; +} + +static size_t +method_xsgetn (FILE *fp, void *data, size_t n) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_xsgetn; + return 0; +} + +static off64_t +method_seekoff (FILE *fp, off64_t offset, int dir, int mode) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_seekoff; + return shared->return_value; +} + +static off64_t +method_seekpos (FILE *fp, off64_t offset, int mode) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_seekpos; + return shared->return_value; +} + +static FILE * +method_setbuf (FILE *fp, char *buffer, ssize_t length) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_setbuf; + return fp; +} + +static int +method_sync (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_sync; + return shared->return_value; +} + +static int +method_doallocate (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_doallocate; + return shared->return_value; +} + +static ssize_t +method_read (FILE *fp, void *data, ssize_t length) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_read; + return shared->return_value; +} + +static ssize_t +method_write (FILE *fp, const void *data, ssize_t length) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_write; + return shared->return_value; +} + +static off64_t +method_seek (FILE *fp, off64_t offset, int mode) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_seek; + return shared->return_value; +} + +static int +method_close (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_close; + return shared->return_value; +} + +static int +method_stat (FILE *fp, void *buffer) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_stat; + return shared->return_value; +} + +static int +method_showmanyc (FILE *fp) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_showmanyc; + return shared->return_value; +} + +static void +method_imbue (FILE *fp, void *locale) +{ + log_method (fp, __func__); + TEST_VERIFY (fp == shared->fp); + ++shared->calls; + ++shared->calls_imbue; +} + +/* Our custom vtable. */ + +static const struct _IO_jump_t jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT (finish, method_finish), + JUMP_INIT (overflow, method_overflow), + JUMP_INIT (underflow, method_underflow), + JUMP_INIT (uflow, method_uflow), + JUMP_INIT (pbackfail, method_pbackfail), + JUMP_INIT (xsputn, method_xsputn), + JUMP_INIT (xsgetn, method_xsgetn), + JUMP_INIT (seekoff, method_seekoff), + JUMP_INIT (seekpos, method_seekpos), + JUMP_INIT (setbuf, method_setbuf), + JUMP_INIT (sync, method_sync), + JUMP_INIT (doallocate, method_doallocate), + JUMP_INIT (read, method_read), + JUMP_INIT (write, method_write), + JUMP_INIT (seek, method_seek), + JUMP_INIT (close, method_close), + JUMP_INIT (stat, method_stat), + JUMP_INIT (showmanyc, method_showmanyc), + JUMP_INIT (imbue, method_imbue) +}; + +/* Our file implementation. */ + +struct my_file +{ + FILE f; + const struct _IO_jump_t *vtable; +}; + +struct my_file +my_file_create (void) +{ + return (struct my_file) + { + /* Disable locking, so that we do not have to set up a lock + pointer. */ + .f._flags = _IO_USER_LOCK, + + /* Copy the offset from the an initialized handle, instead of + figuring it out from scratch. */ + .f._vtable_offset = stdin->_vtable_offset, + + .vtable = &jumps, + }; +} + +/* Initial tests which do not enable vtable compatibility. */ + +/* Inhibit GCC optimization of fprintf. */ +typedef int (*fprintf_type) (FILE *, const char *, ...); +static const volatile fprintf_type fprintf_ptr = &fprintf; + +static void +without_compatibility_fprintf (void *closure) +{ + /* This call should abort. */ + fprintf_ptr (shared->fp, " "); + _exit (1); +} + +static void +without_compatibility_fputc (void *closure) +{ + /* This call should abort. */ + fputc (' ', shared->fp); + _exit (1); +} + +static void +without_compatibility_fgetc (void *closure) +{ + /* This call should abort. */ + fgetc (shared->fp); + _exit (1); +} + +static void +without_compatibility_fflush (void *closure) +{ + /* This call should abort. */ + fflush (shared->fp); + _exit (1); +} + +/* Exit status after abnormal termination. */ +static int termination_status; + +static void +init_termination_status (void) +{ + pid_t pid = xfork (); + if (pid == 0) + abort (); + xwaitpid (pid, &termination_status, 0); + + TEST_VERIFY (WIFSIGNALED (termination_status)); + TEST_COMPARE (WTERMSIG (termination_status), SIGABRT); +} + +static void +check_for_termination (const char *name, void (*callback) (void *)) +{ + struct my_file file = my_file_create (); + shared->fp = &file.f; + shared->return_value = -1; + shared->calls = 0; + struct support_capture_subprocess proc + = support_capture_subprocess (callback, NULL); + support_capture_subprocess_check (&proc, name, termination_status, + sc_allow_stderr); + const char *message + = "Fatal error: glibc detected an invalid stdio handle\n"; + TEST_COMPARE_BLOB (proc.err.buffer, proc.err.length, + message, strlen (message)); + TEST_COMPARE (shared->calls, 0); + support_capture_subprocess_free (&proc); +} + +/* The test with vtable validation disabled. */ + +/* This function does not have a prototype in libioP.h to prevent + accidental use from within the library (which would disable vtable + verification). */ +void _IO_init (FILE *fp, int flags); + +static void +with_compatibility_fprintf (void *closure) +{ + TEST_COMPARE (fprintf_ptr (shared->fp, "A%sCD", "B"), 4); + TEST_COMPARE (shared->calls, 3); + TEST_COMPARE (shared->calls_xsputn, 3); + TEST_COMPARE_BLOB (shared->buffer, shared->buffer_length, + "CD", 2); +} + +static void +with_compatibility_fputc (void *closure) +{ + shared->return_value = '@'; + TEST_COMPARE (fputc ('@', shared->fp), '@'); + TEST_COMPARE (shared->calls, 1); + TEST_COMPARE (shared->calls_overflow, 1); + TEST_COMPARE (shared->value, '@'); +} + +static void +with_compatibility_fgetc (void *closure) +{ + shared->return_value = 'X'; + TEST_COMPARE (fgetc (shared->fp), 'X'); + TEST_COMPARE (shared->calls, 1); + TEST_COMPARE (shared->calls_uflow, 1); +} + +static void +with_compatibility_fflush (void *closure) +{ + TEST_COMPARE (fflush (shared->fp), 0); + TEST_COMPARE (shared->calls, 1); + TEST_COMPARE (shared->calls_sync, 1); +} + +/* Call CALLBACK in a subprocess, after setting up a custom file + object and updating shared->fp. */ +static void +check_call (const char *name, void (*callback) (void *), + bool initially_disabled) +{ + *shared = (struct shared) + { + .initially_disabled = initially_disabled, + }; + + /* Set up a custom file object. */ + struct my_file file = my_file_create (); + shared->fp = &file.f; + if (shared->initially_disabled) + _IO_init (shared->fp, file.f._flags); + + if (test_verbose > 0) + printf ("info: calling test %s\n", name); + support_isolate_in_subprocess (callback, NULL); +} + +/* Run the tests. INITIALLY_DISABLED indicates whether custom vtables + are disabled when the test starts. */ +static int +run_tests (bool initially_disabled) +{ + /* The test relies on fatal error messages being printed to standard + error. */ + setenv ("LIBC_FATAL_STDERR_", "1", 1); + + shared = support_shared_allocate (sizeof (*shared)); + shared->initially_disabled = initially_disabled; + init_termination_status (); + + if (initially_disabled) + { + check_for_termination ("fprintf", without_compatibility_fprintf); + check_for_termination ("fputc", without_compatibility_fputc); + check_for_termination ("fgetc", without_compatibility_fgetc); + check_for_termination ("fflush", without_compatibility_fflush); + } + + check_call ("fprintf", with_compatibility_fprintf, initially_disabled); + check_call ("fputc", with_compatibility_fputc, initially_disabled); + check_call ("fgetc", with_compatibility_fgetc, initially_disabled); + check_call ("fflush", with_compatibility_fflush, initially_disabled); + + support_shared_free (shared); + shared = NULL; + + return 0; +} diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c new file mode 100644 index 0000000000..c8f4e8c7c3 --- /dev/null +++ b/libio/tst-vtables-interposed.c @@ -0,0 +1,37 @@ +/* Test for libio vtables and their validation. Enabled through interposition. + 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 + . */ + +/* Provide an interposed definition of the standard file handles with + our own vtable. stdout/stdin/stderr will not work as a result, but + a succesful test does not print anything, so this is fine. */ +static const struct _IO_jump_t jumps; +#define _IO_file_jumps jumps +#include "stdfiles.c" + +#include "tst-vtables-common.c" + +static int +do_test (void) +{ + return run_tests (false); +} + +/* Calling setvbuf in the test driver is not supported with our + interposed file handles. */ +#define TEST_NO_SETVBUF +#include diff --git a/libio/tst-vtables.c b/libio/tst-vtables.c new file mode 100644 index 0000000000..f16acf5d23 --- /dev/null +++ b/libio/tst-vtables.c @@ -0,0 +1,29 @@ +/* Test for libio vtables and their validation. Initially disabled case. + 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 + . */ + +#include "libioP.h" + +#include "tst-vtables-common.c" + +static int +do_test (void) +{ + return run_tests (true); +} + +#include -- cgit 1.4.1 From b12bed3e061af6df02e7f685fb465235513bb171 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 3 Jul 2018 18:34:26 +0200 Subject: stdio-common/tst-printf.c: Remove part under a non-free license [BZ #23363] The license does not allow modification. Reviewed-by: Carlos O'Donell (cherry picked from commit 5a357506659f9a00fcf5bc9c5d8fc676175c89a7) --- ChangeLog | 7 +++++ LICENSES | 9 ------ NEWS | 1 + stdio-common/tst-printf.c | 70 ---------------------------------------------- stdio-common/tst-printf.sh | 42 ---------------------------- 5 files changed, 8 insertions(+), 121 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7a700da223..f6933f6e8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2018-07-03 Florian Weimer + + [BZ #23363] + * stdio-common/tst-printf.c (DEC, INT, UNS, fp_test): Remove. + * stdio-common/tst-printf.sh: Adjust expected output. + * LICENSES: Update. + 2018-06-26 Florian Weimer * libio/Makefile (tests-internal): Add tst-vtables, diff --git a/LICENSES b/LICENSES index 80f7f14879..858076d9d3 100644 --- a/LICENSES +++ b/LICENSES @@ -441,15 +441,6 @@ Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. -Part of stdio-common/tst-printf.c is copyright C E Chew: - -(C) Copyright C E Chew - -Feel free to copy, use and distribute this software provided: - - 1. you do not pretend that you wrote it - 2. you leave this copyright notice intact. - Various long double libm functions are copyright Stephen L. Moshier: Copyright 2001 by Stephen L. Moshier diff --git a/NEWS b/NEWS index c0b9398e83..fa6218105a 100644 --- a/NEWS +++ b/NEWS @@ -146,6 +146,7 @@ The following bugs are resolved with this release: [23236] Harden function pointers in _IO_str_fields [23313] libio: Disable vtable validation in case of interposition [23349] Various glibc headers no longer compatible with + [23363] stdio-common/tst-printf.c has non-free license Version 2.26 diff --git a/stdio-common/tst-printf.c b/stdio-common/tst-printf.c index b6d62a5a2f..9829e3ec6a 100644 --- a/stdio-common/tst-printf.c +++ b/stdio-common/tst-printf.c @@ -69,75 +69,7 @@ fmtst2chk (const char *fmt) (void) printf(fmt, 4, 4, 0x12); (void) printf("'\n"); } - -/* This page is covered by the following copyright: */ - -/* (C) Copyright C E Chew - * - * Feel free to copy, use and distribute this software provided: - * - * 1. you do not pretend that you wrote it - * 2. you leave this copyright notice intact. - */ - -/* - * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. - */ -#define DEC -123 -#define INT 255 -#define UNS (~0) - -/* Formatted Output Test - * - * This exercises the output formatting code. - */ - -static void -fp_test (void) -{ - int i, j, k, l; - char buf[7]; - char *prefix = buf; - char tp[20]; - - puts("\nFormatted output test"); - printf("prefix 6d 6o 6x 6X 6u\n"); - strcpy(prefix, "%"); - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - for (l = 0; l < 2; l++) { - strcpy(prefix, "%"); - if (i == 0) strcat(prefix, "-"); - if (j == 0) strcat(prefix, "+"); - if (k == 0) strcat(prefix, "#"); - if (l == 0) strcat(prefix, "0"); - printf("%5s |", prefix); - strcpy(tp, prefix); - strcat(tp, "6d |"); - printf(tp, DEC); - strcpy(tp, prefix); - strcat(tp, "6o |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6x |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6X |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6u |"); - printf(tp, UNS); - printf("\n"); - } - } - } - } - printf("%10s\n", (char *) NULL); - printf("%-10s\n", (char *) NULL); -} - static int do_test (void) { @@ -235,8 +167,6 @@ I am ready for my first lesson today."; snprintf(buf2, sizeof(buf2), "%.999999u", 10)); } - fp_test (); - printf ("%e should be 1.234568e+06\n", 1234567.8); printf ("%f should be 1234567.800000\n", 1234567.8); printf ("%g should be 1.23457e+06\n", 1234567.8); diff --git a/stdio-common/tst-printf.sh b/stdio-common/tst-printf.sh index c413980dd3..5948ca2ca3 100644 --- a/stdio-common/tst-printf.sh +++ b/stdio-common/tst-printf.sh @@ -103,27 +103,6 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000 | 123456.0000| 1.2346e+05| 1.235e+05| snprintf ("%30s", "foo") == 30, " " snprintf ("%.999999u", 10) == 999999 - -Formatted output test -prefix 6d 6o 6x 6X 6u -%-+#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-+# |-123 |0377 |0xff |0XFF |4294967295 | - %-+0 |-123 |377 |ff |FF |4294967295 | - %-+ |-123 |377 |ff |FF |4294967295 | - %-#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-# |-123 |0377 |0xff |0XFF |4294967295 | - %-0 |-123 |377 |ff |FF |4294967295 | - %- |-123 |377 |ff |FF |4294967295 | - %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %+# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %+0 |-00123 |000377 |0000ff |0000FF |4294967295 | - %+ | -123 | 377 | ff | FF |4294967295 | - %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %0 |-00123 |000377 |0000ff |0000FF |4294967295 | - % | -123 | 377 | ff | FF |4294967295 | - (null) -(null) 1.234568e+06 should be 1.234568e+06 1234567.800000 should be 1234567.800000 1.23457e+06 should be 1.23457e+06 @@ -219,27 +198,6 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000 | 123456.0000| 1.2346e+05| 1.235e+05| snprintf ("%30s", "foo") == 30, " " snprintf ("%.999999u", 10) == 999999 - -Formatted output test -prefix 6d 6o 6x 6X 6u -%-+#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-+# |-123 |0377 |0xff |0XFF |4294967295 | - %-+0 |-123 |377 |ff |FF |4294967295 | - %-+ |-123 |377 |ff |FF |4294967295 | - %-#0 |-123 |0377 |0xff |0XFF |4294967295 | - %-# |-123 |0377 |0xff |0XFF |4294967295 | - %-0 |-123 |377 |ff |FF |4294967295 | - %- |-123 |377 |ff |FF |4294967295 | - %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %+# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %+0 |-00123 |000377 |0000ff |0000FF |4294967295 | - %+ | -123 | 377 | ff | FF |4294967295 | - %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 | - %# | -123 | 0377 | 0xff | 0XFF |4294967295 | - %0 |-00123 |000377 |0000ff |0000FF |4294967295 | - % | -123 | 377 | ff | FF |4294967295 | - (null) -(null) 1.234568e+06 should be 1.234568e+06 1234567.800000 should be 1234567.800000 1.23457e+06 should be 1.23457e+06 -- cgit 1.4.1 From cf6deb084bcc68d3e0753270b46c2098c76d829c Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Fri, 6 Jul 2018 16:31:24 +0200 Subject: conform/conformtest.pl: Escape literal braces in regular expressions This suppresses Perl warnings like these: Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.32), passed through in regex; marked by <-- HERE in m/^element *({ <-- HERE ([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/ at conformtest.pl line 370. Reviewed-by: Carlos O'Donell (cherry picked from commit ddb3c626b0a159de3547d901420198b626c29554) --- ChangeLog | 5 +++++ conform/conformtest.pl | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6933f6e8a..39d910f3e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-07-06 Florian Weimer + + * conform/conformtest.pl (checknamespace): Escape literal braces + in regular expressions. + 2018-07-03 Florian Weimer [BZ #23363] diff --git a/conform/conformtest.pl b/conform/conformtest.pl index cb500f0e76..a4ef756105 100644 --- a/conform/conformtest.pl +++ b/conform/conformtest.pl @@ -367,7 +367,7 @@ while ($#headers >= 0) { s/^optional-//; $optional = 1; } - if (/^element *({([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) { + if (/^element *(\{([^}]*)\}|([^{ ]*)) *(\{([^}]*)\}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) { my($struct) = "$2$3"; my($type) = "$5$6"; my($member) = "$7"; @@ -556,7 +556,7 @@ while ($#headers >= 0) { "Symbol \"$symbol\" has not the right value.", $res, $xfail); } - } elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) { + } elsif (/^type *(\{([^}]*)|([a-zA-Z0-9_]*))/) { my($type) = "$2$3"; my($maybe_opaque) = 0; @@ -586,7 +586,7 @@ while ($#headers >= 0) { ? "NOT AVAILABLE" : "Type \"$type\" not available."), $missing, $optional, $xfail); - } elsif (/^tag *({([^}]*)|([a-zA-Z0-9_]*))/) { + } elsif (/^tag *(\{([^}]*)|([a-zA-Z0-9_]*))/) { my($type) = "$2$3"; # Remember that this name is allowed. @@ -607,7 +607,7 @@ while ($#headers >= 0) { compiletest ($fnamebase, "Testing for type $type", "Type \"$type\" not available.", $missing, 0, $xfail); - } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { my($rettype) = "$2$3"; my($fname) = "$4"; my($args) = "$5"; @@ -644,7 +644,7 @@ while ($#headers >= 0) { "Function \"$fname\" has incorrect type.", $res, 0, $xfail); } - } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { my($rettype) = "$2$3"; my($fname) = "$4"; my($args) = "$5"; @@ -681,7 +681,7 @@ while ($#headers >= 0) { "Function \"$fname\" has incorrect type.", $res, 0, $xfail); } - } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) *(.*)/) { + } elsif (/^variable *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) *(.*)/) { my($type) = "$2$3"; my($vname) = "$4"; my($rest) = "$5"; @@ -713,7 +713,7 @@ while ($#headers >= 0) { compiletest ($fnamebase, "Test for type of variable $fname", "Variable \"$vname\" has incorrect type.", $res, 0, $xfail); - } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^macro-function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { my($rettype) = "$2$3"; my($fname) = "$4"; my($args) = "$5"; @@ -812,11 +812,11 @@ while ($#headers >= 0) { s/^xfail(\[([^\]]*)\])?-//; s/^optional-//; - if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) { + if (/^element *(\{([^}]*)\}|([^ ]*)) *(\{([^}]*)\}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) { push @allow, $7; } elsif (/^(macro|constant|macro-constant|macro-int-constant) +([a-zA-Z0-9_]*) *(?:{([^}]*)} *)?(?:([>== 0) { } else { push @allow, $type; } - } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) { push @allow, $4; - } elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { push @allow, $4; - } elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) { + } elsif (/^variable *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) { push @allow, $4; - } elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { + } elsif (/^macro-function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) { push @allow, $4; } elsif (/^symbol *([a-zA-Z0-9_]*) *([A-Za-z0-9_-]*)?/) { push @allow, $1; -- cgit 1.4.1 From 86e0996b1a02b3b46185f5fd28b78f0223956008 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 29 Jul 2018 06:08:59 -0700 Subject: x86: Correct index_cpu_LZCNT [BZ #23456] cpu-features.h has #define bit_cpu_LZCNT (1 << 5) #define index_cpu_LZCNT COMMON_CPUID_INDEX_1 #define reg_LZCNT But the LZCNT feature bit is in COMMON_CPUID_INDEX_80000001: Initial EAX Value: 80000001H ECX Extended Processor Signature and Feature Bits: Bit 05: LZCNT available index_cpu_LZCNT should be COMMON_CPUID_INDEX_80000001, not COMMON_CPUID_INDEX_1. The VMX feature bit is in COMMON_CPUID_INDEX_1: Initial EAX Value: 01H Feature Information Returned in the ECX Register: 5 VMX Reviewed-by: Carlos O'Donell [BZ #23456] * sysdeps/x86/cpu-features.h (index_cpu_LZCNT): Set to COMMON_CPUID_INDEX_80000001. (cherry picked from commit 65d87ade1ee6f3ac099105e3511bd09bdc24cf3f) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/x86/cpu-features.h | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 39d910f3e2..831579524d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-07-29 H.J. Lu + + [BZ #23456] + * sysdeps/x86/cpu-features.h (index_cpu_LZCNT): Set to + COMMON_CPUID_INDEX_80000001. + 2018-07-06 Florian Weimer * conform/conformtest.pl (checknamespace): Escape literal braces diff --git a/NEWS b/NEWS index fa6218105a..e0c11b1ea9 100644 --- a/NEWS +++ b/NEWS @@ -147,6 +147,7 @@ The following bugs are resolved with this release: [23313] libio: Disable vtable validation in case of interposition [23349] Various glibc headers no longer compatible with [23363] stdio-common/tst-printf.c has non-free license + [23456] Wrong index_cpu_LZCNT Version 2.26 diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h index 1d88f7a68c..a6fae06014 100644 --- a/sysdeps/x86/cpu-features.h +++ b/sysdeps/x86/cpu-features.h @@ -292,7 +292,7 @@ extern const struct cpu_features *__get_cpu_features (void) # define index_cpu_HTT COMMON_CPUID_INDEX_1 # define index_cpu_BMI1 COMMON_CPUID_INDEX_7 # define index_cpu_BMI2 COMMON_CPUID_INDEX_7 -# define index_cpu_LZCNT COMMON_CPUID_INDEX_1 +# define index_cpu_LZCNT COMMON_CPUID_INDEX_80000001 # define index_cpu_MOVBE COMMON_CPUID_INDEX_1 # define index_cpu_POPCNT COMMON_CPUID_INDEX_1 -- cgit 1.4.1 From c9570bd2f54abb68e4e3c767aca3a54e05d2c7f6 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 29 Jul 2018 06:08:59 -0700 Subject: x86: Populate COMMON_CPUID_INDEX_80000001 for Intel CPUs [BZ #23459] Reviewed-by: Carlos O'Donell [BZ #23459] * sysdeps/x86/cpu-features.c (get_extended_indices): New function. (init_cpu_features): Call get_extended_indices for both Intel and AMD CPUs. * sysdeps/x86/cpu-features.h (COMMON_CPUID_INDEX_80000001): Remove "for AMD" comment. (cherry picked from commit be525a69a6630abc83144c0a96474f2e26da7443) --- ChangeLog | 10 ++++++++++ NEWS | 1 + sysdeps/x86/cpu-features.c | 27 ++++++++++++++++++--------- sysdeps/x86/cpu-features.h | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 831579524d..7e22bd1dfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2018-07-29 H.J. Lu + + [BZ #23459] + * sysdeps/x86/cpu-features.c (get_extended_indices): New + function. + (init_cpu_features): Call get_extended_indices for both Intel + and AMD CPUs. + * sysdeps/x86/cpu-features.h (COMMON_CPUID_INDEX_80000001): + Remove "for AMD" comment. + 2018-07-29 H.J. Lu [BZ #23456] diff --git a/NEWS b/NEWS index e0c11b1ea9..61ac02cd69 100644 --- a/NEWS +++ b/NEWS @@ -148,6 +148,7 @@ The following bugs are resolved with this release: [23349] Various glibc headers no longer compatible with [23363] stdio-common/tst-printf.c has non-free license [23456] Wrong index_cpu_LZCNT + [23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors Version 2.26 diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c index 87aaa8683c..a66d468b20 100644 --- a/sysdeps/x86/cpu-features.c +++ b/sysdeps/x86/cpu-features.c @@ -30,6 +30,20 @@ extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden; #endif +static void +get_extended_indices (struct cpu_features *cpu_features) +{ + unsigned int eax, ebx, ecx, edx; + __cpuid (0x80000000, eax, ebx, ecx, edx); + if (eax >= 0x80000001) + __cpuid (0x80000001, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].eax, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ebx, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ecx, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].edx); + +} + static void get_common_indeces (struct cpu_features *cpu_features, unsigned int *family, unsigned int *model, @@ -205,6 +219,8 @@ init_cpu_features (struct cpu_features *cpu_features) get_common_indeces (cpu_features, &family, &model, &extended_model, &stepping); + get_extended_indices (cpu_features); + if (family == 0x06) { model += extended_model; @@ -324,16 +340,9 @@ init_cpu_features (struct cpu_features *cpu_features) get_common_indeces (cpu_features, &family, &model, &extended_model, &stepping); - ecx = cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx; + get_extended_indices (cpu_features); - unsigned int eax; - __cpuid (0x80000000, eax, ebx, ecx, edx); - if (eax >= 0x80000001) - __cpuid (0x80000001, - cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].eax, - cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ebx, - cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ecx, - cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].edx); + ecx = cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx; if (HAS_ARCH_FEATURE (AVX_Usable)) { diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h index a6fae06014..e4eb6bf41a 100644 --- a/sysdeps/x86/cpu-features.h +++ b/sysdeps/x86/cpu-features.h @@ -196,7 +196,7 @@ enum { COMMON_CPUID_INDEX_1 = 0, COMMON_CPUID_INDEX_7, - COMMON_CPUID_INDEX_80000001, /* for AMD */ + COMMON_CPUID_INDEX_80000001, /* Keep the following line at the end. */ COMMON_CPUID_INDEX_MAX }; -- cgit 1.4.1 From 174709d879a15590e00119c7f91dc2460aaf571c Mon Sep 17 00:00:00 2001 From: Martin Kuchta Date: Mon, 27 Aug 2018 18:54:46 +0200 Subject: pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538] (cherry picked from commit 99ea93ca31795469d2a1f1570f17a5c39c2eb7e2) --- ChangeLog | 8 ++++++++ NEWS | 1 + nptl/pthread_cond_common.c | 8 ++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e22bd1dfc..2b771ca994 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-08-27 Martin Kuchta + Torvald Riegel + + [BZ #23538] + * nptl/pthread_cond_common.c (__condvar_quiesce_and_switch_g1): + Update r to include the set wake-request flag if waiters are + remaining after spinning. + 2018-07-29 H.J. Lu [BZ #23459] diff --git a/NEWS b/NEWS index 61ac02cd69..a868a652f7 100644 --- a/NEWS +++ b/NEWS @@ -146,6 +146,7 @@ The following bugs are resolved with this release: [23236] Harden function pointers in _IO_str_fields [23313] libio: Disable vtable validation in case of interposition [23349] Various glibc headers no longer compatible with + [23538] pthread_cond_broadcast: Fix waiters-after-spinning case [23363] stdio-common/tst-printf.c has non-free license [23456] Wrong index_cpu_LZCNT [23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c index ffbbde4106..c99435e439 100644 --- a/nptl/pthread_cond_common.c +++ b/nptl/pthread_cond_common.c @@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq, { /* There is still a waiter after spinning. Set the wake-request flag and block. Relaxed MO is fine because this is just about - this futex word. */ - r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1); + this futex word. + + Update r to include the set wake-request flag so that the upcoming + futex_wait only blocks if the flag is still set (otherwise, we'd + violate the basic client-side futex protocol). */ + r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1; if ((r >> 1) > 0) futex_wait_simple (cond->__data.__g_refs + g1, r, private); -- cgit 1.4.1 From c5c90b480e4f21ed1d28e0e6d942b06b8d9e8bd7 Mon Sep 17 00:00:00 2001 From: Stefan Liebler Date: Thu, 6 Sep 2018 14:27:03 +0200 Subject: Fix segfault in maybe_script_execute. If glibc is built with gcc 8 and -march=z900, the testcase posix/tst-spawn4-compat crashes with a segfault. In function maybe_script_execute, the new_argv array is dynamically initialized on stack with (argc + 1) elements. The function wants to add _PATH_BSHELL as the first argument and writes out of bounds of new_argv. There is an off-by-one because maybe_script_execute fails to count the terminating NULL when sizing new_argv. ChangeLog: * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): Increment size of new_argv by one. (cherry picked from commit 28669f86f6780a18daca264f32d66b1428c9c6f1) --- ChangeLog | 5 +++++ sysdeps/unix/sysv/linux/spawni.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2b771ca994..6848c7d550 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-09-06 Stefan Liebler + + * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): + Increment size of new_argv by one. + 2018-08-27 Martin Kuchta Torvald Riegel diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c index 7d23df84d2..2d7502adaa 100644 --- a/sysdeps/unix/sysv/linux/spawni.c +++ b/sysdeps/unix/sysv/linux/spawni.c @@ -101,7 +101,7 @@ maybe_script_execute (struct posix_spawn_args *args) ptrdiff_t argc = args->argc; /* Construct an argument list for the shell. */ - char *new_argv[argc + 1]; + char *new_argv[argc + 2]; new_argv[0] = (char *) _PATH_BSHELL; new_argv[1] = (char *) args->file; if (argc > 1) -- cgit 1.4.1 From 3022a296bd4106caf3121401d4cd80d32f6c8631 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Fri, 2 Feb 2018 10:46:26 +0100 Subject: preadv2/pwritev2: Handle offset == -1 [BZ #22753] Reviewed-by: Adhemerval Zanella (cherry picked from commit d4b4a00a462348750bb18544eb30853ee6ac5d10) --- ChangeLog | 17 ++++++++++++++++ NEWS | 1 + manual/llio.texi | 21 ++++++++++++------- misc/tst-preadvwritev-common.c | 38 +++++++++++++++++++++++++++++++++++ misc/tst-preadvwritev2.c | 1 + misc/tst-preadvwritev64v2.c | 1 + sysdeps/posix/preadv2.c | 5 ++++- sysdeps/posix/preadv64v2.c | 5 ++++- sysdeps/posix/pwritev2.c | 5 ++++- sysdeps/posix/pwritev64v2.c | 5 ++++- sysdeps/unix/sysv/linux/preadv2.c | 5 ++++- sysdeps/unix/sysv/linux/preadv64v2.c | 6 +++++- sysdeps/unix/sysv/linux/pwritev2.c | 5 ++++- sysdeps/unix/sysv/linux/pwritev64v2.c | 5 ++++- 14 files changed, 105 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6848c7d550..4baa85bcfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2018-09-28 Florian Weimer + + [BZ #22753] + * sysdeps/posix/preadv2.c (preadv2): Handle offset == -1. + * sysdeps/posix/preadv64v2.c (preadv64v2): Likewise. + * sysdeps/posix/pwritev2.c (pwritev2): Likewise. + * sysdeps/posix/pwritev64v2.c (pwritev64v2): Likweise. + * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Likewise. + * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. + * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. + * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likweise. + * manual/llio.texi (Scatter-Gather): Mention offset -1. + * misc/tst-preadvwritev-common.c (do_test_without_offset): New. + * misc/tst-preadvwritev2.c (do_test): Call it. + * misc/tst-preadvwritev64v2.c (do_test): Likewise. + * NEWS: Add bug fixed. + 2018-09-06 Stefan Liebler * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): diff --git a/NEWS b/NEWS index a868a652f7..d5e3403e8b 100644 --- a/NEWS +++ b/NEWS @@ -135,6 +135,7 @@ The following bugs are resolved with this release: (CVE-2018-1000001) [22685] powerpc: Fix syscalls during early process initialization [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE + [22753] libc: preadv2/pwritev2 fallback code should handle offset=-1 [22774] malloc: Integer overflow in malloc (CVE-2018-6551) [22786] Fix path length overflow in realpath [23005] resolv: Fix crash in resolver on memory allocation failure diff --git a/manual/llio.texi b/manual/llio.texi index e72c53c785..4ce9ee360e 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -754,9 +754,13 @@ When the source file is compiled using @code{_FILE_OFFSET_BITS == 64} on a @c This is a syscall for Linux v4.6. The sysdeps/posix fallback emulation @c is also MT-Safe since it calls preadv. -This function is similar to the @code{preadv} function, with the difference -it adds an extra @var{flags} parameter of type @code{int}. The supported -@var{flags} are dependent of the underlying system. For Linux it supports: +This function is similar to the @code{preadv} function, with the +difference it adds an extra @var{flags} parameter of type @code{int}. +Additionally, if @var{offset} is @math{-1}, the current file position +is used and updated (like the @code{readv} function). + +The supported @var{flags} are dependent of the underlying system. For +Linux it supports: @vtable @code @item RWF_HIPRI @@ -823,10 +827,13 @@ When the source file is compiled using @code{_FILE_OFFSET_BITS == 64} on a @c This is a syscall for Linux v4.6. The sysdeps/posix fallback emulation @c is also MT-Safe since it calls pwritev. -This function is similar to the @code{pwritev} function, with the difference -it adds an extra @var{flags} parameter of type @code{int}. The supported -@var{flags} are dependent of the underlying system and for Linux it supports -the same ones as for @code{preadv2}. +This function is similar to the @code{pwritev} function, with the +difference it adds an extra @var{flags} parameter of type @code{int}. +Additionally, if @var{offset} is @math{-1}, the current file position +should is used and updated (like the @code{writev} function). + +The supported @var{flags} are dependent of the underlying system. For +Linux, the supported flags are the same as those for @code{preadv2}. When the source file is compiled with @code{_FILE_OFFSET_BITS == 64} the @code{pwritev2} function is in fact @code{pwritev64v2} and the type diff --git a/misc/tst-preadvwritev-common.c b/misc/tst-preadvwritev-common.c index 676d4953ac..7f9a63f1f5 100644 --- a/misc/tst-preadvwritev-common.c +++ b/misc/tst-preadvwritev-common.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -25,6 +26,7 @@ #include #include +#include static char *temp_filename; static int temp_fd; @@ -50,6 +52,42 @@ do_prepare (int argc, char **argv) pwritev (__fd, __iov, __iovcnt, __offset) #endif +static __attribute__ ((unused)) void +do_test_without_offset (void) +{ + xftruncate (temp_fd, 0); + + xwrite (temp_fd, "123", 3); + xlseek (temp_fd, 2, SEEK_SET); + { + struct iovec iov[] = + { + { (void *) "abc", 3 }, + { (void *) "xyzt", 4 }, + }; + TEST_COMPARE (PWRITEV (temp_fd, iov, array_length (iov), -1), 7); + } + TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 9); + + xlseek (temp_fd, 1, SEEK_SET); + char buf1[3]; + char buf2[2]; + { + struct iovec iov[] = + { + { buf1, sizeof (buf1) }, + { buf2, sizeof (buf2) }, + }; + TEST_COMPARE (PREADV (temp_fd, iov, array_length (iov), -1), + sizeof (buf1) + sizeof (buf2)); + TEST_COMPARE (memcmp ("2ab", buf1, sizeof (buf1)), 0); + TEST_COMPARE (memcmp ("cx", buf2, sizeof (buf2)), 0); + TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 6); + } + + xftruncate (temp_fd, 0); +} + static int do_test_with_offset (off_t offset) { diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c index 682c7579da..225f5e59c1 100644 --- a/misc/tst-preadvwritev2.c +++ b/misc/tst-preadvwritev2.c @@ -29,6 +29,7 @@ static int do_test (void) { do_test_with_invalid_flags (); + do_test_without_offset (); return do_test_with_offset (0); } diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c index 9ddc7625f0..facdbdca61 100644 --- a/misc/tst-preadvwritev64v2.c +++ b/misc/tst-preadvwritev64v2.c @@ -31,6 +31,7 @@ static int do_test (void) { do_test_with_invalid_flags (); + do_test_without_offset (); return do_test_with_offset (0); } diff --git a/sysdeps/posix/preadv2.c b/sysdeps/posix/preadv2.c index d27f7028ed..fe73d3cbea 100644 --- a/sysdeps/posix/preadv2.c +++ b/sysdeps/posix/preadv2.c @@ -32,7 +32,10 @@ preadv2 (int fd, const struct iovec *vector, int count, OFF_T offset, return -1; } - return preadv (fd, vector, count, offset); + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv (fd, vector, count, offset); } #endif diff --git a/sysdeps/posix/preadv64v2.c b/sysdeps/posix/preadv64v2.c index ce7cb40bf2..8569c8b398 100644 --- a/sysdeps/posix/preadv64v2.c +++ b/sysdeps/posix/preadv64v2.c @@ -29,7 +29,10 @@ preadv64v2 (int fd, const struct iovec *vector, int count, OFF_T offset, return -1; } - return preadv64 (fd, vector, count, offset); + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv64 (fd, vector, count, offset); } #ifdef __OFF_T_MATCHES_OFF64_T diff --git a/sysdeps/posix/pwritev2.c b/sysdeps/posix/pwritev2.c index 7ec8cbc407..b24b491a81 100644 --- a/sysdeps/posix/pwritev2.c +++ b/sysdeps/posix/pwritev2.c @@ -32,7 +32,10 @@ pwritev2 (int fd, const struct iovec *vector, int count, OFF_T offset, return -1; } - return pwritev (fd, vector, count, offset); + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev (fd, vector, count, offset); } #endif diff --git a/sysdeps/posix/pwritev64v2.c b/sysdeps/posix/pwritev64v2.c index be98aeed9d..ae4c4284c2 100644 --- a/sysdeps/posix/pwritev64v2.c +++ b/sysdeps/posix/pwritev64v2.c @@ -30,7 +30,10 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, OFF_T offset, return -1; } - return pwritev64 (fd, vector, count, offset); + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev64 (fd, vector, count, offset); } #ifdef __OFF_T_MATCHES_OFF64_T diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c index 137e2dd791..a7a3aeeee6 100644 --- a/sysdeps/unix/sysv/linux/preadv2.c +++ b/sysdeps/unix/sysv/linux/preadv2.c @@ -49,7 +49,10 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, __set_errno (ENOTSUP); return -1; } - return preadv (fd, vector, count, offset); + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv (fd, vector, count, offset); } #endif diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c index 8f413253f4..53c946861c 100644 --- a/sysdeps/unix/sysv/linux/preadv64v2.c +++ b/sysdeps/unix/sysv/linux/preadv64v2.c @@ -47,7 +47,11 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, __set_errno (ENOTSUP); return -1; } - return preadv64 (fd, vector, count, offset); + + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv64 (fd, vector, count, offset); } #ifdef __OFF_T_MATCHES_OFF64_T diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c index 8e5032fe2f..17677df98d 100644 --- a/sysdeps/unix/sysv/linux/pwritev2.c +++ b/sysdeps/unix/sysv/linux/pwritev2.c @@ -45,7 +45,10 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, __set_errno (ENOTSUP); return -1; } - return pwritev (fd, vector, count, offset); + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev (fd, vector, count, offset); } #endif diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c index d2800c6657..f5753eede5 100644 --- a/sysdeps/unix/sysv/linux/pwritev64v2.c +++ b/sysdeps/unix/sysv/linux/pwritev64v2.c @@ -47,7 +47,10 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, __set_errno (ENOTSUP); return -1; } - return pwritev64 (fd, vector, count, offset); + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev64 (fd, vector, count, offset); } #ifdef __OFF_T_MATCHES_OFF64_T -- cgit 1.4.1 From 202d08db40f297e718699f628e3c2111be335c2c Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Wed, 29 Aug 2018 16:36:44 -0300 Subject: Fix misreported errno on preadv2/pwritev2 (BZ#23579) The fallback code of Linux wrapper for preadv2/pwritev2 executes regardless of the errno code for preadv2, instead of the case where the syscall is not supported. This fixes it by calling the fallback code iff errno is ENOSYS. The patch also adds tests for both invalid file descriptor and invalid iov_len and vector count. The only discrepancy between preadv2 and fallback code regarding error reporting is when an invalid flags are used. The fallback code bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall is used. Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel. [BZ #23579] * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New test. * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): Call do_test_with_invalid_fd. * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff errno is ENOSYS. * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. (cherry picked from commit 7a16bdbb9ff4122af0a28dc20996c95352011fdd) --- ChangeLog | 14 +++++++ NEWS | 1 + misc/tst-preadvwritev2-common.c | 77 ++++++++++++++++++++++++++++++++++- misc/tst-preadvwritev2.c | 2 + misc/tst-preadvwritev64v2.c | 2 + sysdeps/unix/sysv/linux/preadv2.c | 2 +- sysdeps/unix/sysv/linux/preadv64v2.c | 2 +- sysdeps/unix/sysv/linux/pwritev2.c | 2 +- sysdeps/unix/sysv/linux/pwritev64v2.c | 2 +- 9 files changed, 99 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4baa85bcfc..faa13471fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2018-09-28 Adhemerval Zanella + + [BZ #23579] + * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd, + do_test_with_invalid_iov): New tests. + * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): + Call do_test_with_invalid_fd and do_test_with_invalid_iov. + * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff + errno is ENOSYS. + * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. + * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. + * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. + * NEWS: Add bug fixed. + 2018-09-28 Florian Weimer [BZ #22753] diff --git a/NEWS b/NEWS index d5e3403e8b..299fba24b1 100644 --- a/NEWS +++ b/NEWS @@ -151,6 +151,7 @@ The following bugs are resolved with this release: [23363] stdio-common/tst-printf.c has non-free license [23456] Wrong index_cpu_LZCNT [23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors + [23579] libc: Errors misreported in preadv2 Version 2.26 diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c index 8abedc14d0..9570882fa6 100644 --- a/misc/tst-preadvwritev2-common.c +++ b/misc/tst-preadvwritev2-common.c @@ -19,10 +19,85 @@ #include #include +#ifndef RWF_HIPRI +# define RWF_HIPRI 0 +#endif +#ifndef RWF_DSYNC +# define RWF_DSYNC 0 +#endif +#ifndef RWF_SYNC +# define RWF_SYNC 0 +#endif +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0 +#endif +#ifndef RWF_APPEND +# define RWF_APPEND 0 +#endif +#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \ + | RWF_APPEND) + +static void +do_test_with_invalid_fd (void) +{ + char buf[256]; + struct iovec iov = { buf, sizeof buf }; + + /* Check with flag being 0 to use the fallback code which calls pwritev + or writev. */ + TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1); + TEST_COMPARE (errno, EBADF); + TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1); + TEST_COMPARE (errno, EBADF); + + /* Same tests as before but with flags being different than 0. Since + there is no emulation for any flag value, fallback code returns + ENOTSUP. This is different running on a kernel with preadv2/pwritev2 + support, where EBADF is returned). */ + TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EBADF || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EBADF || errno == ENOTSUP); +} + +static void +do_test_with_invalid_iov (void) +{ + { + char buf[256]; + struct iovec iov; + + iov.iov_base = buf; + iov.iov_len = (size_t)SSIZE_MAX + 1; + + TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1); + TEST_COMPARE (errno, EINVAL); + TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1); + TEST_COMPARE (errno, EINVAL); + + /* Same as for invalid file descriptor tests, emulation fallback + first checks for flag value and return ENOTSUP. */ + TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + } + + { + /* An invalid iovec buffer should trigger an invalid memory access + or an error (Linux for instance returns EFAULT). */ + struct iovec iov[IOV_MAX+1] = { 0 }; + + TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + } +} + static void do_test_with_invalid_flags (void) { -#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT) /* Set the next bit from the mask of all supported flags. */ int invalid_flag = __builtin_clz (RWF_SUPPORTED); invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag); diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c index 225f5e59c1..bebd2e56d6 100644 --- a/misc/tst-preadvwritev2.c +++ b/misc/tst-preadvwritev2.c @@ -30,6 +30,8 @@ do_test (void) { do_test_with_invalid_flags (); do_test_without_offset (); + do_test_with_invalid_fd (); + do_test_with_invalid_iov (); return do_test_with_offset (0); } diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c index facdbdca61..3d03e32484 100644 --- a/misc/tst-preadvwritev64v2.c +++ b/misc/tst-preadvwritev64v2.c @@ -32,6 +32,8 @@ do_test (void) { do_test_with_invalid_flags (); do_test_without_offset (); + do_test_with_invalid_fd (); + do_test_with_invalid_iov (); return do_test_with_offset (0); } diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c index a7a3aeeee6..c7f91025f2 100644 --- a/sysdeps/unix/sysv/linux/preadv2.c +++ b/sysdeps/unix/sysv/linux/preadv2.c @@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, # ifdef __NR_preadv2 ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; # endif /* Trying to emulate the preadv2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c index 53c946861c..4dbea0a8d4 100644 --- a/sysdeps/unix/sysv/linux/preadv64v2.c +++ b/sysdeps/unix/sysv/linux/preadv64v2.c @@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, #ifdef __NR_preadv64v2 ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; #endif /* Trying to emulate the preadv2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c index 17677df98d..a33ed56c55 100644 --- a/sysdeps/unix/sysv/linux/pwritev2.c +++ b/sysdeps/unix/sysv/linux/pwritev2.c @@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, # ifdef __NR_pwritev2 ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; # endif /* Trying to emulate the pwritev2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c index f5753eede5..f0ffd2f1f6 100644 --- a/sysdeps/unix/sysv/linux/pwritev64v2.c +++ b/sysdeps/unix/sysv/linux/pwritev64v2.c @@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, #ifdef __NR_pwritev64v2 ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; #endif /* Trying to emulate the pwritev2 syscall flags is troublesome: -- cgit 1.4.1 From 48bef587bfd4b6c11ae227075eb1492b10a395a8 Mon Sep 17 00:00:00 2001 From: "Ilya Yu. Malakhov" Date: Mon, 22 Oct 2018 13:43:59 +0200 Subject: signal: Use correct type for si_band in siginfo_t [BZ #23562] (cherry picked from commit f997b4be18f7e57d757d39e42f7715db26528aa0) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/unix/sysv/linux/bits/types/siginfo_t.h | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index faa13471fb..9f47705871 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-10-19 Ilya Yu. Malakhov + + [BZ #23562] + * sysdeps/unix/sysv/linux/bits/types/siginfo_t.h + (struct siginfo_t): Use correct type for si_band. + 2018-09-28 Adhemerval Zanella [BZ #23579] diff --git a/NEWS b/NEWS index 299fba24b1..33bc5196c8 100644 --- a/NEWS +++ b/NEWS @@ -151,6 +151,7 @@ The following bugs are resolved with this release: [23363] stdio-common/tst-printf.c has non-free license [23456] Wrong index_cpu_LZCNT [23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors + [23562] signal: Use correct type for si_band in siginfo_t [23579] libc: Errors misreported in preadv2 Version 2.26 diff --git a/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h b/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h index bed69148f9..18d60bc705 100644 --- a/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h +++ b/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h @@ -107,7 +107,7 @@ typedef struct /* SIGPOLL. */ struct { - long int si_band; /* Band event for SIGPOLL. */ + __SI_BAND_TYPE si_band; /* Band event for SIGPOLL. */ int si_fd; } _sigpoll; -- cgit 1.4.1 From 27611fd05b444042de4a718c2f21e9efae755825 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 22 Nov 2017 18:44:23 +0000 Subject: Avoid use of strlen in getlogin_r (bug 22447). Building glibc with current mainline GCC fails, among other reasons, because of an error for use of strlen on the nonstring ut_user field. This patch changes the problem code in getlogin_r to use __strnlen instead. It also needs to set the trailing NUL byte of the result explicitly, because of the case where ut_user does not have such a trailing NUL byte (but the result should always have one). Tested for x86_64. Also tested that, in conjunction with , it fixes the build for arm with mainline GCC. [BZ #22447] * sysdeps/unix/getlogin_r.c (__getlogin_r): Use __strnlen not strlen to compute length of ut_user and set trailing NUL byte of result explicitly. (cherry picked from commit 4bae615022cb5a5da79ccda83cc6c9ba9f2d479c) --- ChangeLog | 7 +++++++ NEWS | 1 + sysdeps/unix/getlogin_r.c | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f47705871..8f5098701c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-11-22 Joseph Myers + + [BZ #22447] + * sysdeps/unix/getlogin_r.c (__getlogin_r): Use __strnlen not + strlen to compute length of ut_user and set trailing NUL byte of + result explicitly. + 2018-10-19 Ilya Yu. Malakhov [BZ #23562] diff --git a/NEWS b/NEWS index 33bc5196c8..5569e8d8d2 100644 --- a/NEWS +++ b/NEWS @@ -127,6 +127,7 @@ The following bugs are resolved with this release: [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) [22377] Provide a C++ version of iseqsig [22442] if_nametoindex: Check length of ifname before copying it + [22447] Avoid use of strlen in getlogin_r [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice [22636] PTHREAD_STACK_MIN is too small on x86-64 [22637] nptl: Fix stack guard size accounting diff --git a/sysdeps/unix/getlogin_r.c b/sysdeps/unix/getlogin_r.c index 4a6a40eeb2..ad8e9111f6 100644 --- a/sysdeps/unix/getlogin_r.c +++ b/sysdeps/unix/getlogin_r.c @@ -80,7 +80,7 @@ __getlogin_r (char *name, size_t name_len) if (result == 0) { - size_t needed = strlen (ut->ut_user) + 1; + size_t needed = __strnlen (ut->ut_user, UT_NAMESIZE) + 1; if (needed > name_len) { @@ -89,7 +89,8 @@ __getlogin_r (char *name, size_t name_len) } else { - memcpy (name, ut->ut_user, needed); + memcpy (name, ut->ut_user, needed - 1); + name[needed - 1] = 0; result = 0; } } -- cgit 1.4.1 From e37ec9c813de3faeabc31d9ffc896ba45b4dfd5f Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 15 Nov 2017 17:39:59 -0700 Subject: utmp: Avoid -Wstringop-truncation warning The -Wstringop-truncation option new in GCC 8 detects common misuses of the strncat and strncpy function that may result in truncating the copied string before the terminating NUL. To avoid false positive warnings for correct code that intentionally creates sequences of characters that aren't guaranteed to be NUL-terminated, arrays that are intended to store such sequences should be decorated with a new nonstring attribute. This change add this attribute to Glibc and uses it to suppress such false positives. ChangeLog: * misc/sys/cdefs.h (__attribute_nonstring__): New macro. * sysdeps/gnu/bits/utmp.h (struct utmp): Use it. * sysdeps/unix/sysv/linux/s390/bits/utmp.h (struct utmp): Same. (cherry picked from commit 7532837d7b03b3ca5b9a63d77a5bd81dd23f3d9c) --- ChangeLog | 6 ++++++ misc/sys/cdefs.h | 9 +++++++++ sysdeps/gnu/bits/utmp.h | 9 ++++++--- sysdeps/unix/sysv/linux/s390/bits/utmp.h | 9 ++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f5098701c..e2febbcce5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-11-15 Martin Sebor + + * misc/sys/cdefs.h (__attribute_nonstring__): New macro. + * sysdeps/gnu/bits/utmp.h (struct utmp): Use it. + * sysdeps/unix/sysv/linux/s390/bits/utmp.h (struct utmp): Same. + 2017-11-22 Joseph Myers [BZ #22447] diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 0c808216a4..41261fea39 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -408,6 +408,15 @@ # endif #endif +#if __GNUC_PREREQ (8, 0) +/* Describes a char array whose address can safely be passed as the first + argument to strncpy and strncat, as the char array is not necessarily + a NUL-terminated string. */ +# define __attribute_nonstring__ __attribute__ ((__nonstring__)) +#else +# define __attribute_nonstring__ +#endif + #if (!defined _Static_assert && !defined __cplusplus \ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ && (!__GNUC_PREREQ (4, 6) || defined __STRICT_ANSI__)) diff --git a/sysdeps/gnu/bits/utmp.h b/sysdeps/gnu/bits/utmp.h index 2ee11cb706..71c9fa2a9f 100644 --- a/sysdeps/gnu/bits/utmp.h +++ b/sysdeps/gnu/bits/utmp.h @@ -59,10 +59,13 @@ struct utmp { short int ut_type; /* Type of login. */ pid_t ut_pid; /* Process ID of login process. */ - char ut_line[UT_LINESIZE]; /* Devicename. */ + char ut_line[UT_LINESIZE] + __attribute_nonstring__; /* Devicename. */ char ut_id[4]; /* Inittab ID. */ - char ut_user[UT_NAMESIZE]; /* Username. */ - char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ + char ut_user[UT_NAMESIZE] + __attribute_nonstring__; /* Username. */ + char ut_host[UT_HOSTSIZE] + __attribute_nonstring__; /* Hostname for remote login. */ struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS. */ /* The ut_session and ut_tv fields must be the same size when compiled diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmp.h b/sysdeps/unix/sysv/linux/s390/bits/utmp.h index 36114c3b0e..f754f374b5 100644 --- a/sysdeps/unix/sysv/linux/s390/bits/utmp.h +++ b/sysdeps/unix/sysv/linux/s390/bits/utmp.h @@ -59,10 +59,13 @@ struct utmp { short int ut_type; /* Type of login. */ pid_t ut_pid; /* Process ID of login process. */ - char ut_line[UT_LINESIZE]; /* Devicename. */ + char ut_line[UT_LINESIZE] + __attribute_nonstring__; /* Devicename. */ char ut_id[4]; /* Inittab ID. */ - char ut_user[UT_NAMESIZE]; /* Username. */ - char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ + char ut_user[UT_NAMESIZE] + __attribute_nonstring__; /* Username. */ + char ut_host[UT_HOSTSIZE] + __attribute_nonstring__; /* Hostname for remote login. */ struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS. */ /* The ut_session and ut_tv fields must be the same size when compiled -- cgit 1.4.1 From d161b294e1267ca275352c26850255c5efc998de Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 12 Nov 2017 22:00:28 -0800 Subject: timezone: pacify GCC -Wstringop-truncation Problem reported by Martin Sebor in: https://sourceware.org/ml/libc-alpha/2017-11/msg00336.html * timezone/zic.c (writezone): Use memcpy, not strncpy. (cherry picked from commit e69897bf202e18034cbef26f363bae64de70a196) --- ChangeLog | 7 +++++++ timezone/zic.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e2febbcce5..9109e38a85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-11-12 Paul Eggert + + timezone: pacify GCC -Wstringop-truncation + Problem reported by Martin Sebor in: + https://sourceware.org/ml/libc-alpha/2017-11/msg00336.html + * timezone/zic.c (writezone): Use memcpy, not strncpy. + 2017-11-15 Martin Sebor * misc/sys/cdefs.h (__attribute_nonstring__): New macro. diff --git a/timezone/zic.c b/timezone/zic.c index 946bf6ff8e..e738386600 100644 --- a/timezone/zic.c +++ b/timezone/zic.c @@ -1949,7 +1949,7 @@ writezone(const char *const name, const char *const string, char version) } #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp) tzh = tzh0; - strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); + memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); tzh.tzh_version[0] = version; convert(thistypecnt, tzh.tzh_ttisgmtcnt); convert(thistypecnt, tzh.tzh_ttisstdcnt); -- cgit 1.4.1 From 636f49ba925d5fe677212bb94b20f2c5e67d4a4f Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 22 Oct 2018 13:58:06 +0200 Subject: Fix p_secstodate overflow handling (bug 22463). The resolv/res_debug.c function p_secstodate (which is a public function exported from libresolv, taking an unsigned long argument) does: struct tm timebuf; time = __gmtime_r(&clock, &timebuf); time->tm_year += 1900; time->tm_mon += 1; sprintf(output, "%04d%02d%02d%02d%02d%02d", time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); If __gmtime_r returns NULL (because the year overflows the range of int), this will dereference a null pointer. Otherwise, if the computed year does not fit in four characters, this will cause a buffer overrun of the fixed-size 15-byte buffer. With current GCC mainline, there is a compilation failure because of the possible buffer overrun. I couldn't find a specification for how this function is meant to behave, but Paul pointed to RFC 4034 as relevant to the cases where this function is called from within glibc. The function's interface is inherently problematic when dates beyond Y2038 might be involved, because of the ambiguity in how to interpret 32-bit timestamps as such dates (the RFC suggests interpreting times as being within 68 years of the present date, which would mean some kind of interface whose behavior depends on the present date). This patch works on the basis of making a minimal fix in preparation for obsoleting the function. The function is made to handle times in the interval [0, 0x7fffffff] only, on all platforms, with used as the output string in other cases (and errno set to EOVERFLOW in such cases). This seems to be a reasonable state for the function to be in when made a compat symbol by a future patch, being compatible with any existing uses for existing timestamps without trying to work for later timestamps. Results independent of the range of time_t also simplify the testcase. I couldn't persuade GCC to recognize the ranges of the struct tm fields by adding explicit range checks with a call to __builtin_unreachable if outside the range (this looks similar to ), so having added a range check on the input, this patch then disables the -Wformat-overflow= warning for the sprintf call (I prefer that to the use of strftime, as being more transparently correct without knowing what each of %m and %M etc. is). I do not know why this build failure should be new with mainline GCC (that is, I don't know what GCC change might have introduced it, when the basic functionality for such warnings was already in GCC 7). I do not know if this is a security issue (that is, if there are plausible ways in which a date before -999 or after 9999 from an untrusted source might end up in this function). The system clock is arguably an untrusted source (in that e.g. NTP is insecure), but probably not to that extent (NTP can't communicate such wild timestamps), and uses from within glibc are limited to 32-bit inputs. Tested with build-many-glibcs.py that this restores the build for arm with yesterday's mainline GCC. Also tested for x86_64 and x86. [BZ #22463] * resolv/res_debug.c: Include . (p_secstodate): Assert time_t at least as wide as u_long. On overflow, use integer seconds since the epoch as output, or use "" as output and set errno to EOVERFLOW if integer seconds since the epoch would be 14 or more characters. (p_secstodate) [__GNUC_PREREQ (7, 0)]: Disable -Wformat-overflow= for sprintf call. * resolv/tst-p_secstodate.c: New file. * resolv/Makefile (tests): Add tst-p_secstodate. ($(objpfx)tst-p_secstodate): Depend on $(objpfx)libresolv.so. (cherry picked from commit f120cda6072d830df92656dad0c89967547b97dc) --- ChangeLog | 14 ++++++++++ NEWS | 1 + resolv/Makefile | 3 ++- resolv/res_debug.c | 24 ++++++++++++++++- resolv/tst-p_secstodate.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 resolv/tst-p_secstodate.c diff --git a/ChangeLog b/ChangeLog index 9109e38a85..022cbc65af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2017-11-22 Joseph Myers + + [BZ #22463] + * resolv/res_debug.c: Include . + (p_secstodate): Assert time_t at least as wide as u_long. On + overflow, use integer seconds since the epoch as output, or use + "" as output and set errno to EOVERFLOW if integer + seconds since the epoch would be 14 or more characters. + (p_secstodate) [__GNUC_PREREQ (7, 0)]: Disable -Wformat-overflow= + for sprintf call. + * resolv/tst-p_secstodate.c: New file. + * resolv/Makefile (tests): Add tst-p_secstodate. + ($(objpfx)tst-p_secstodate): Depend on $(objpfx)libresolv.so. + 2017-11-12 Paul Eggert timezone: pacify GCC -Wstringop-truncation diff --git a/NEWS b/NEWS index 5569e8d8d2..fecdbdf103 100644 --- a/NEWS +++ b/NEWS @@ -128,6 +128,7 @@ The following bugs are resolved with this release: [22377] Provide a C++ version of iseqsig [22442] if_nametoindex: Check length of ifname before copying it [22447] Avoid use of strlen in getlogin_r + [22463] Fix p_secstodate overflow handling [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice [22636] PTHREAD_STACK_MIN is too small on x86-64 [22637] nptl: Fix stack guard size accounting diff --git a/resolv/Makefile b/resolv/Makefile index ec7e4fd146..8eb405a741 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -53,6 +53,7 @@ tests += \ tst-resolv-network \ tst-resolv-res_init-multi \ tst-resolv-search \ + tst-p_secstodate \ # These tests need libdl. ifeq (yes,$(build-shared)) @@ -178,7 +179,7 @@ $(objpfx)tst-resolv-canonname: \ $(objpfx)tst-ns_name: $(objpfx)libresolv.so $(objpfx)tst-ns_name.out: tst-ns_name.data $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so - +$(objpfx)tst-p_secstodate: $(objpfx)libresolv.so # This test case uses the deprecated RES_USE_INET6 resolver option. CFLAGS-tst-res_use_inet6.c += -Wno-error diff --git a/resolv/res_debug.c b/resolv/res_debug.c index 919b86e2b3..154a4f8e24 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -107,6 +107,7 @@ #include #include #include +#include #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) @@ -1054,6 +1055,8 @@ libresolv_hidden_def (__dn_count_labels) /* * Make dates expressed in seconds-since-Jan-1-1970 easy to read. * SIG records are required to be printed like this, by the Secure DNS RFC. + * This is an obsolescent function and does not handle dates outside the + * signed 32-bit range. */ char * p_secstodate (u_long secs) { @@ -1063,12 +1066,31 @@ p_secstodate (u_long secs) { struct tm *time; struct tm timebuf; - time = __gmtime_r(&clock, &timebuf); + /* The call to __gmtime_r can never produce a year overflowing + the range of int, given the check on SECS, but check for a + NULL return anyway to avoid a null pointer dereference in + case there are any other unspecified errors. */ + if (secs > 0x7fffffff + || (time = __gmtime_r (&clock, &timebuf)) == NULL) { + strcpy (output, ""); + __set_errno (EOVERFLOW); + return output; + } time->tm_year += 1900; time->tm_mon += 1; + /* The struct tm fields, given the above range check, + must have values that mean this sprintf exactly fills the + buffer. But as of GCC 8 of 2017-11-21, GCC cannot tell + that, even given range checks on all fields with + __builtin_unreachable called for out-of-range values. */ + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow="); +#endif sprintf(output, "%04d%02d%02d%02d%02d%02d", time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); + DIAG_POP_NEEDS_COMMENT; return (output); } libresolv_hidden_def (__p_secstodate) diff --git a/resolv/tst-p_secstodate.c b/resolv/tst-p_secstodate.c new file mode 100644 index 0000000000..9dac1ad819 --- /dev/null +++ b/resolv/tst-p_secstodate.c @@ -0,0 +1,67 @@ +/* Test p_secstodate. + Copyright (C) 2017 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 +#include +#include +#include + +struct test +{ + /* Argument to p_secstodate. */ + unsigned long int in; + /* Expected output. */ + const char *out; +}; + +static const struct test tests[] = + { + { 0UL, "19700101000000" }, + { 12345UL, "19700101032545" }, + { 999999999UL, "20010909014639" }, + { 2147483647UL, "20380119031407" }, + { 2147483648UL, "" }, + { 4294967295UL, "" }, +#if ULONG_MAX > 0xffffffffUL + { 4294967296UL, "" }, + { 9999999999UL, "" }, + { LONG_MAX, "" }, + { ULONG_MAX, "" }, +#endif + }; + +static int +do_test (void) +{ + int ret = 0; + for (size_t i = 0; i < array_length (tests); i++) + { + char *p = p_secstodate (tests[i].in); + printf ("Test %zu: %lu -> %s\n", i, tests[i].in, p); + if (strcmp (p, tests[i].out) != 0) + { + printf ("test %zu failed", i); + ret = 1; + } + } + return ret; +} + +#include -- cgit 1.4.1 From 3fb525c1033c70693d78010d01472bd0ed96e25f Mon Sep 17 00:00:00 2001 From: Steve Ellcey Date: Fri, 15 Dec 2017 09:08:23 -0800 Subject: Increase buffer size due to warning from ToT GCC * nscd/dbg_log.c (dbg_log): Increase msg buffer size. (cherry picked from commit a7e3edf4f252fb72afeb8ecca946a2d8294bb577) --- ChangeLog | 4 ++++ nscd/dbg_log.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 022cbc65af..49bcd10abc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2017-12-15 Steve Ellcey + + * nscd/dbg_log.c (dbg_log): Increase msg buffer size. + 2017-11-22 Joseph Myers [BZ #22463] diff --git a/nscd/dbg_log.c b/nscd/dbg_log.c index d4b19acc0c..2190c16ce5 100644 --- a/nscd/dbg_log.c +++ b/nscd/dbg_log.c @@ -67,7 +67,7 @@ dbg_log (const char *fmt,...) char buf[256]; strftime (buf, sizeof (buf), "%c", &now); - char msg[512]; + char msg[1024]; snprintf (msg, sizeof (msg), "%s - %d: %s%s", buf, getpid (), msg2, msg2[strlen (msg2) - 1] == '\n' ? "" : "\n"); if (dbgout) -- cgit 1.4.1 From 935cecfe9a4c9bf0396766f5e2b24570f92317ae Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 22 Oct 2018 14:08:12 +0200 Subject: Fix nscd readlink argument aliasing (bug 22446). Current GCC mainline detects that nscd calls readlink with the same buffer for both input and output, which is not valid (those arguments are both restrict-qualified in POSIX). This patch makes it use a separate buffer for readlink's input (with a size that is sufficient to avoid truncation, so there should be no problems with warnings about possible truncation, though not strictly minimal, but much smaller than the buffer for output) to avoid this problem. Tested compilation for aarch64-linux-gnu with build-many-glibcs.py. [BZ #22446] * nscd/connections.c (handle_request) [SO_PEERCRED]: Use separate buffers for readlink input and output. (cherry picked from commit 49b036bce9f021ae994a85aee8b410d20b29c8b7) --- ChangeLog | 6 ++++++ NEWS | 1 + nscd/connections.c | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49bcd10abc..0b7a920673 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-12-18 Joseph Myers + + [BZ #22446] + * nscd/connections.c (handle_request) [SO_PEERCRED]: Use separate + buffers for readlink input and output. + 2017-12-15 Steve Ellcey * nscd/dbg_log.c (dbg_log): Increase msg buffer size. diff --git a/NEWS b/NEWS index fecdbdf103..f6c9a1412c 100644 --- a/NEWS +++ b/NEWS @@ -127,6 +127,7 @@ The following bugs are resolved with this release: [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426) [22377] Provide a C++ version of iseqsig [22442] if_nametoindex: Check length of ifname before copying it + [22446] Fix nscd readlink argument aliasing [22447] Avoid use of strlen in getlogin_r [22463] Fix p_secstodate overflow handling [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice diff --git a/nscd/connections.c b/nscd/connections.c index cc1ed72077..dab722dcb2 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1077,14 +1077,15 @@ cannot handle old request version %d; current version is %d"), if (debug_level > 0) { #ifdef SO_PEERCRED + char pbuf[sizeof ("/proc//exe") + 3 * sizeof (long int)]; # ifdef PATH_MAX char buf[PATH_MAX]; # else char buf[4096]; # endif - snprintf (buf, sizeof (buf), "/proc/%ld/exe", (long int) pid); - ssize_t n = readlink (buf, buf, sizeof (buf) - 1); + snprintf (pbuf, sizeof (pbuf), "/proc/%ld/exe", (long int) pid); + ssize_t n = readlink (pbuf, buf, sizeof (buf) - 1); if (n <= 0) dbg_log (_("\ -- cgit 1.4.1 From dd03d15e283de6c2fff8f5204b092e9d9d127cc6 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 14 Nov 2017 17:52:26 +0000 Subject: Fix string/tester.c build with GCC 8. GCC 8 warns about more cases of string functions truncating their output or not copying a trailing NUL byte. This patch fixes testsuite build failures caused by such warnings in string/tester.c. In general, the warnings are disabled around the relevant calls using DIAG_* macros, since the relevant cases are being deliberately tested. In one case, the warning is with -Wstringop-overflow= instead of -Wstringop-truncation; in that case, the conditional is __GNUC_PREREQ (7, 0) (being the version where -Wstringop-overflow= was introduced), to allow the conditional to be removed sooner, since it's harmless to disable the warning for a GCC version where it doesn't actually occur. In the case of warnings for strncpy calls in test_memcmp, the calls in question are changed to use memcpy, as they don't copy a trailing NUL and the point of that code is to test memcmp rather than strncpy. Tested (compilation) with GCC 8 for x86_64-linux-gnu with build-many-glibcs.py (in conjunction with Martin's patch to allow glibc to build). * string/tester.c (test_stpncpy): Disable -Wstringop-truncation for stpncpy calls for GCC 8. (test_strncat): Disable -Wstringop-truncation warning for strncat calls for GCC 8. Disable -Wstringop-overflow= warning for one strncat call for GCC 7. (test_strncpy): Disable -Wstringop-truncation warning for strncpy calls for GCC 8. (test_memcmp): Use memcpy instead of strncpy for calls not copying trailing NUL. (cherry picked from commit 2e64ec9c9eac3aeb70f7cfa2392846c87c28068e) --- ChangeLog | 12 ++++++++++++ string/tester.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b7a920673..3d3d364b4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2017-11-14 Joseph Myers + + * string/tester.c (test_stpncpy): Disable -Wstringop-truncation + for stpncpy calls for GCC 8. + (test_strncat): Disable -Wstringop-truncation warning for strncat + calls for GCC 8. Disable -Wstringop-overflow= warning for one + strncat call for GCC 7. + (test_strncpy): Disable -Wstringop-truncation warning for strncpy + calls for GCC 8. + (test_memcmp): Use memcpy instead of strncpy for calls not copying + trailing NUL. + 2017-12-18 Joseph Myers [BZ #22446] diff --git a/string/tester.c b/string/tester.c index 4b928b4f5e..66b11515b0 100644 --- a/string/tester.c +++ b/string/tester.c @@ -264,8 +264,15 @@ test_stpncpy (void) { it = "stpncpy"; memset (one, 'x', sizeof (one)); + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about stpncpy truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif check (stpncpy (one, "abc", 2) == one + 2, 1); check (stpncpy (one, "abc", 3) == one + 3, 2); + DIAG_POP_NEEDS_COMMENT; check (stpncpy (one, "abc", 4) == one + 3, 3); check (one[3] == '\0' && one[4] == 'x', 4); check (stpncpy (one, "abcd", 5) == one + 4, 5); @@ -420,13 +427,27 @@ test_strncat (void) equal (one, "cd", 9); (void) strcpy (one, "ab"); + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about strncat truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif (void) strncat (one, "cdef", 2); + DIAG_POP_NEEDS_COMMENT; equal (one, "abcd", 10); /* Count-limited. */ (void) strncat (one, "gh", 0); equal (one, "abcd", 11); /* Zero count. */ + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* GCC 8 warns about strncat bound equal to source length; this is + deliberately tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-overflow="); +#endif (void) strncat (one, "gh", 2); + DIAG_POP_NEEDS_COMMENT; equal (one, "abcdgh", 12); /* Count and length equal. */ DIAG_PUSH_NEEDS_COMMENT; @@ -523,11 +544,25 @@ test_strncpy (void) equal (one, "abc", 2); /* Did the copy go right? */ (void) strcpy (one, "abcdefgh"); + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about strncpy truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif (void) strncpy (one, "xyz", 2); + DIAG_POP_NEEDS_COMMENT; equal (one, "xycdefgh", 3); /* Copy cut by count. */ (void) strcpy (one, "abcdefgh"); + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about strncpy truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */ + DIAG_POP_NEEDS_COMMENT; equal (one, "xyzdefgh", 4); (void) strcpy (one, "abcdefgh"); @@ -542,7 +577,14 @@ test_strncpy (void) equal (one+5, "fgh", 9); (void) strcpy (one, "abc"); + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about strncpy truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif (void) strncpy (one, "xyz", 0); /* Zero-length copy. */ + DIAG_POP_NEEDS_COMMENT; equal (one, "abc", 10); (void) strncpy (one, "", 2); /* Zero-length source. */ @@ -1151,8 +1193,8 @@ test_memcmp (void) { char *a = one + i; char *b = two + i; - strncpy(a, "--------11112222", 16); - strncpy(b, "--------33334444", 16); + memcpy(a, "--------11112222", 16); + memcpy(b, "--------33334444", 16); check(memcmp(b, a, 16) > 0, cnt++); check(memcmp(a, b, 16) < 0, cnt++); } -- cgit 1.4.1 From 70e810a30cb15d0b54118f8eb92aa656b945b984 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 18 Dec 2017 22:52:41 +0000 Subject: Disable strncat test array-bounds warnings for GCC 8. Some strncat tests fail to build with GCC 8 because of -Warray-bounds warnings. These tests are deliberately test over-large size arguments passed to strncat, and already disable -Wstringop-overflow warnings, but now the warnings for these tests come under -Warray-bounds so that option needs disabling for them as well, which this patch does (with an update on the comments; the DIAG_IGNORE_NEEDS_COMMENT call for -Warray-bounds doesn't need to be conditional itself, because that option is supported by all versions of GCC that can build glibc). Tested compilation with build-many-glibcs.py for aarch64-linux-gnu. * string/tester.c (test_strncat): Also disable -Warray-bounds warnings for two tests. (cherry picked from commit 1421f39b7eadd3b5fbd2a3f2da1fc006b69fbc42) --- ChangeLog | 5 +++++ string/tester.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d3d364b4f..61a3c872a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-12-18 Joseph Myers + + * string/tester.c (test_strncat): Also disable -Warray-bounds + warnings for two tests. + 2017-11-14 Joseph Myers * string/tester.c (test_stpncpy): Disable -Wstringop-truncation diff --git a/string/tester.c b/string/tester.c index 66b11515b0..02ea8e1e16 100644 --- a/string/tester.c +++ b/string/tester.c @@ -387,9 +387,11 @@ test_strncat (void) DIAG_PUSH_NEEDS_COMMENT; #if __GNUC_PREREQ (7, 0) /* GCC 7 warns about the size passed to strncat being larger than - the size of the buffer; this is deliberately tested here.. */ + the size of the buffer; this is deliberately tested here; GCC 8 + gives a -Warray-bounds warning about this. */ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow="); #endif + DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds"); (void) strncat (one, two, 99); DIAG_POP_NEEDS_COMMENT; equal (one, "ghef", 5); /* Basic test encore. */ @@ -480,9 +482,11 @@ test_strncat (void) #if __GNUC_PREREQ (7, 0) /* GCC 7 warns about the size passed to strncat being larger than the size of the buffer; this is - deliberately tested here.. */ + deliberately tested here; GCC 8 gives a -Warray-bounds + warning about this. */ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow="); #endif + DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds"); check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4) == buf1 + n2, ntest); DIAG_POP_NEEDS_COMMENT; -- cgit 1.4.1 From fe5978e1a5d7419de3a779823fb5ed0d1dcee8ff Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 14 Jun 2018 14:20:00 +0000 Subject: Ignore -Wrestrict for one strncat test. With current GCC mainline, one strncat test involving a size close to SIZE_MAX results in a -Wrestrict warning that that buffer size would imply that the two buffers must overlap. This patch fixes the build by adding disabling of -Wrestrict (for GCC versions supporting that option) to the already-present disabling of -Wstringop-overflow= and -Warray-bounds for this test. Tested with build-many-glibcs.py that this restores the testsuite build with GCC mainline for aarch64-linux-gnu. * string/tester.c (test_strncat) [__GNUC_PREREQ (7, 0)]: Also ignore -Wrestrict for one test. (cherry picked from commit 35ebb6b0c48bc671d9c54e089884f9bf6fca540e) --- ChangeLog | 5 +++++ string/tester.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 61a3c872a5..65633dbc7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-06-14 Joseph Myers + + * string/tester.c (test_strncat) [__GNUC_PREREQ (7, 0)]: Also + ignore -Wrestrict for one test. + 2017-12-18 Joseph Myers * string/tester.c (test_strncat): Also disable -Warray-bounds diff --git a/string/tester.c b/string/tester.c index 02ea8e1e16..8fdbe3de13 100644 --- a/string/tester.c +++ b/string/tester.c @@ -485,6 +485,10 @@ test_strncat (void) deliberately tested here; GCC 8 gives a -Warray-bounds warning about this. */ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow="); + /* GCC 9 as of 2018-06-14 warns that the size passed is + large enough that, if it were the actual object size, + the objects would have to overlap. */ + DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict"); #endif DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds"); check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4) -- cgit 1.4.1 From 6ae2ca620a955f1e3465e58b5180c5a7fd596dd0 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 14 Nov 2017 17:50:36 +0000 Subject: Fix string/bug-strncat1.c build with GCC 8. GCC 8 warns about strncat calls with truncated output. string/bug-strncat1.c tests such a call; this patch disables the warning for it. Tested (compilation) with GCC 8 for x86_64-linux-gnu with build-many-glibcs.py (in conjunction with Martin's patch to allow glibc to build). * string/bug-strncat1.c: Include . (main): Disable -Wstringop-truncation for strncat call for GCC 8. (cherry picked from commit ec72135e5f1d061cb5cf7cd1b855fd6290be10d9) --- ChangeLog | 5 +++++ string/bug-strncat1.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index 65633dbc7f..d4223dbb9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-11-14 Joseph Myers + + * string/bug-strncat1.c: Include . + (main): Disable -Wstringop-truncation for strncat call for GCC 8. + 2018-06-14 Joseph Myers * string/tester.c (test_strncat) [__GNUC_PREREQ (7, 0)]: Also diff --git a/string/bug-strncat1.c b/string/bug-strncat1.c index f1b5c37c5c..b22beba4d3 100644 --- a/string/bug-strncat1.c +++ b/string/bug-strncat1.c @@ -4,13 +4,21 @@ #include #include #include +#include char d[3] = "\0\1\2"; int main (void) { + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (8, 0) + /* GCC 8 warns about strncat truncating output; this is deliberately + tested here. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation"); +#endif strncat (d, "\5\6", 1); + DIAG_POP_NEEDS_COMMENT; if (d[0] != '\5') { puts ("d[0] != '\\5'"); -- cgit 1.4.1 From 33f5de7a79b27b9dce30a46d6681974653a85004 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 18 Dec 2017 22:55:28 +0000 Subject: Disable -Wrestrict for two nptl/tst-attr3.c tests. nptl/tst-attr3 fails to build with GCC mainline because of (deliberate) aliasing between the second (attributes) and fourth (argument to thread start routine) arguments to pthread_create. Although both those arguments are restrict-qualified in POSIX, pthread_create does not actually dereference its fourth argument; it's an opaque pointer passed to the thread start routine. Thus, the aliasing is actually valid in this case, and it's deliberate in the test. So this patch makes the test disable -Wrestrict for the two pthread_create calls in question. (-Wrestrict was added in GCC 7, hence the __GNUC_PREREQ conditions, but the particular warning in question is new in GCC 8.) Tested compilation with build-many-glibcs.py for aarch64-linux-gnu. * nptl/tst-attr3.c: Include . (do_test) [__GNUC_PREREQ (7, 0)]: Ignore -Wrestrict for two tests. (cherry picked from commit 40c4162df6766fb1e8ede875ca8df25d8075d3a5) --- ChangeLog | 5 +++++ nptl/tst-attr3.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/ChangeLog b/ChangeLog index d4223dbb9e..c6dfc5e677 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-12-18 Joseph Myers + + * nptl/tst-attr3.c: Include . + (do_test) [__GNUC_PREREQ (7, 0)]: Ignore -Wrestrict for two tests. + 2017-11-14 Joseph Myers * string/bug-strncat1.c: Include . diff --git a/nptl/tst-attr3.c b/nptl/tst-attr3.c index bc23386daf..420a7dba8b 100644 --- a/nptl/tst-attr3.c +++ b/nptl/tst-attr3.c @@ -26,6 +26,7 @@ #include #include +#include static void * tf (void *arg) @@ -362,7 +363,16 @@ do_test (void) result = 1; } + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* GCC 8 warns about aliasing of the restrict-qualified arguments + passed &a. Since pthread_create does not dereference its fourth + argument, this aliasing, which is deliberate in this test, cannot + in fact cause problems. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict"); +#endif err = pthread_create (&th, &a, tf, &a); + DIAG_POP_NEEDS_COMMENT; if (err) { error (0, err, "pthread_create #2 failed"); @@ -388,7 +398,16 @@ do_test (void) result = 1; } + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* GCC 8 warns about aliasing of the restrict-qualified arguments + passed &a. Since pthread_create does not dereference its fourth + argument, this aliasing, which is deliberate in this test, cannot + in fact cause problems. */ + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict"); +#endif err = pthread_create (&th, &a, tf, &a); + DIAG_POP_NEEDS_COMMENT; if (err) { error (0, err, "pthread_create #3 failed"); -- cgit 1.4.1 From dc40423dba7208ded2ec293c9a2938269f944ee8 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Fri, 2 Nov 2018 11:14:05 +0100 Subject: x86: Fix Haswell CPU string flags (BZ#23709) Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the default flags for Haswell models. Previously, new models were handled by the default switch path, which assumed a Core i3/i5/i7 if AVX is available. After the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and Prefer_PMINUB_for_stringop (only the TSX one). This patch fixes it by disentangle the TSX flag handling from the memory optimization ones. The strstr case cited on patch now selects the __strstr_sse2_unaligned as expected for the Haswell cpu. Checked on x86_64-linux-gnu. [BZ #23709] * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits independently of other flags. (cherry picked from commit c3d8dc45c9df199b8334599a6cbd98c9950dba62) --- ChangeLog | 6 ++++++ NEWS | 1 + sysdeps/x86/cpu-features.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index c6dfc5e677..17a9232cdf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-10-23 Adhemerval Zanella + + [BZ #23709] + * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits + independently of other flags. + 2017-12-18 Joseph Myers * nptl/tst-attr3.c: Include . diff --git a/NEWS b/NEWS index f6c9a1412c..d99732fe06 100644 --- a/NEWS +++ b/NEWS @@ -156,6 +156,7 @@ The following bugs are resolved with this release: [23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors [23562] signal: Use correct type for si_band in siginfo_t [23579] libc: Errors misreported in preadv2 + [23709] Fix CPU string flags for Haswell-type CPUs Version 2.26 diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c index a66d468b20..b3a5f4b26a 100644 --- a/sysdeps/x86/cpu-features.c +++ b/sysdeps/x86/cpu-features.c @@ -297,7 +297,13 @@ init_cpu_features (struct cpu_features *cpu_features) | bit_arch_Fast_Unaligned_Copy | bit_arch_Prefer_PMINUB_for_stringop); break; + } + /* Disable TSX on some Haswell processors to avoid TSX on kernels that + weren't updated with the latest microcode package (which disables + broken feature by default). */ + switch (model) + { case 0x3f: /* Xeon E7 v3 with stepping >= 4 has working TSX. */ if (stepping >= 4) -- cgit 1.4.1 From fcd86c62538b465eaf002b0ed8981d00e10b649f Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 6 Nov 2018 17:12:07 +0100 Subject: libanl: properly cleanup if first helper thread creation failed (bug 22927) (cherry picked from commit bd3b0fbae33a9a4cc5e2daf049443d5cf03d4251) --- ChangeLog | 6 ++++++ NEWS | 1 + resolv/gai_misc.c | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17a9232cdf..390b91ca45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-11-05 Andreas Schwab + + [BZ #22927] + * resolv/gai_misc.c (__gai_enqueue_request): Don't crash if + creating the first helper thread failed. + 2018-10-23 Adhemerval Zanella [BZ #23709] diff --git a/NEWS b/NEWS index d99732fe06..3c708d2903 100644 --- a/NEWS +++ b/NEWS @@ -141,6 +141,7 @@ The following bugs are resolved with this release: [22753] libc: preadv2/pwritev2 fallback code should handle offset=-1 [22774] malloc: Integer overflow in malloc (CVE-2018-6551) [22786] Fix path length overflow in realpath + [22927] libanl: properly cleanup if first helper thread creation failed [23005] resolv: Fix crash in resolver on memory allocation failure [23024] getlogin_r: return early when linux sentinel value is set [23037] resolv: Fully initialize struct mmsghdr in send_dg diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c index fd9aa356be..5e5e4b82fe 100644 --- a/resolv/gai_misc.c +++ b/resolv/gai_misc.c @@ -264,8 +264,11 @@ __gai_enqueue_request (struct gaicb *gaicbp) /* We cannot create a thread in the moment and there is also no thread running. This is a problem. `errno' is set to EAGAIN if this is only a temporary problem. */ - assert (lastp->next == newp); - lastp->next = NULL; + assert (requests == newp || lastp->next == newp); + if (lastp != NULL) + lastp->next = NULL; + else + requests = NULL; requests_tail = lastp; newp->next = freelist; -- cgit 1.4.1 From 27e46f5836d69c3e82442b1e3ac8a8b5e9ab12ce Mon Sep 17 00:00:00 2001 From: Alexandra Hájková Date: Fri, 19 Oct 2018 13:30:44 +0200 Subject: Add an additional test to resolv/tst-resolv-network.c Test for the infinite loop in getnetbyname, bug #17630. (cherry picked from commit ac8060265bcaca61568ef3a20b9a0140a270af54) --- ChangeLog | 5 +++++ resolv/tst-resolv-network.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index 390b91ca45..23724daa2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-11-08 Alexandra Hájková + + [BZ #17630] + * resolv/tst-resolv-network.c: Add test for getnetbyname. + 2018-11-05 Andreas Schwab [BZ #22927] diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c index df9daf8d58..65ce9634cc 100644 --- a/resolv/tst-resolv-network.c +++ b/resolv/tst-resolv-network.c @@ -149,6 +149,9 @@ handle_code (const struct resolv_response_context *ctx, resolv_response_add_data (b, &rrtype, sizeof (rrtype)); } break; + case 104: + send_ptr (b, qname, qclass, qtype, "host.example"); + break; default: FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code); } @@ -257,6 +260,9 @@ main (void) "error: TRY_AGAIN\n"); check_netent ("code103.example", getnetbyname ("code103.example"), "error: NO_RECOVERY\n"); + /* Test bug #17630. */ + check_netent ("code104.example", getnetbyname ("code104.example"), + "error: TRY_AGAIN\n"); /* Lookup by address, success cases. */ check_reverse (1, -- cgit 1.4.1 From a0bc5dd3bed4b04814047265b3bcead7ab973b87 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 27 Nov 2018 16:12:43 +0100 Subject: CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927] (cherry picked from commit d527c860f5a3f0ed687bd03f0cb464612dc23408) --- ChangeLog | 7 +++++++ NEWS | 5 +++++ sysdeps/unix/sysv/linux/if_index.c | 11 ++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 23724daa2f..2d3af62685 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2018-11-27 Florian Weimer + + [BZ #23927] + CVE-2018-19591 + * sysdeps/unix/sysv/linux/if_index.c (__if_nametoindex): Avoid + descriptor leak in case of ENODEV error. + 2018-11-08 Alexandra Hájková [BZ #17630] diff --git a/NEWS b/NEWS index 3c708d2903..f6d26425ff 100644 --- a/NEWS +++ b/NEWS @@ -82,6 +82,10 @@ Security related changes: architecture could write beyond the target buffer, resulting in a buffer overflow. Reported by Andreas Schwab. + CVE-2018-19591: A file descriptor leak in if_nametoindex can lead to a + denial of service due to resource exhaustion when processing getaddrinfo + calls with crafted host names. Reported by Guido Vranken. + The following bugs are resolved with this release: [16750] ldd: Never run file directly. @@ -158,6 +162,7 @@ The following bugs are resolved with this release: [23562] signal: Use correct type for si_band in siginfo_t [23579] libc: Errors misreported in preadv2 [23709] Fix CPU string flags for Haswell-type CPUs + [23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591) Version 2.26 diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index a874634d52..b620d21936 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -38,11 +38,6 @@ __if_nametoindex (const char *ifname) return 0; #else struct ifreq ifr; - int fd = __opensock (); - - if (fd < 0) - return 0; - if (strlen (ifname) >= IFNAMSIZ) { __set_errno (ENODEV); @@ -50,6 +45,12 @@ __if_nametoindex (const char *ifname) } strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + + int fd = __opensock (); + + if (fd < 0) + return 0; + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) { int saved_errno = errno; -- cgit 1.4.1 From 94417f6c26d6e6a2f0728b8e2cdacfb939689bce Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 31 Dec 2018 22:04:36 +0100 Subject: malloc: Always call memcpy in _int_realloc [BZ #24027] This commit removes the custom memcpy implementation from _int_realloc for small chunk sizes. The ncopies variable has the wrong type, and an integer wraparound could cause the existing code to copy too few elements (leaving the new memory region mostly uninitialized). Therefore, removing this code fixes bug 24027. (cherry picked from commit b50dd3bc8cbb1efe85399b03d7e6c0310c2ead84) --- ChangeLog | 7 +++++++ NEWS | 1 + malloc/malloc.c | 43 +------------------------------------------ 3 files changed, 9 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d3af62685..b5727c7585 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2018-12-31 Florian Weimer + + [BZ #24027] + * malloc/malloc.c (_int_realloc): Always call memcpy for the + copying operation. (ncopies had the wrong type, resulting in an + integer wraparound and too few elements being copied.) + 2018-11-27 Florian Weimer [BZ #23927] diff --git a/NEWS b/NEWS index f6d26425ff..ef857b6e6c 100644 --- a/NEWS +++ b/NEWS @@ -163,6 +163,7 @@ The following bugs are resolved with this release: [23579] libc: Errors misreported in preadv2 [23709] Fix CPU string flags for Haswell-type CPUs [23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591) + [24027] malloc: Integer overflow in realloc Version 2.26 diff --git a/malloc/malloc.c b/malloc/malloc.c index 862337466e..49e8ed69c2 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -4528,11 +4528,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, mchunkptr bck; /* misc temp for linking */ mchunkptr fwd; /* misc temp for linking */ - unsigned long copysize; /* bytes to copy */ - unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ - INTERNAL_SIZE_T* s; /* copy source */ - INTERNAL_SIZE_T* d; /* copy destination */ - /* oldmem size */ if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0) || __builtin_expect (oldsize >= av->system_mem, 0)) @@ -4600,43 +4595,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, } else { - /* - Unroll copy of <= 36 bytes (72 if 8byte sizes) - We know that contents have an odd number of - INTERNAL_SIZE_T-sized words; minimally 3. - */ - - copysize = oldsize - SIZE_SZ; - s = (INTERNAL_SIZE_T *) (chunk2mem (oldp)); - d = (INTERNAL_SIZE_T *) (newmem); - ncopies = copysize / sizeof (INTERNAL_SIZE_T); - assert (ncopies >= 3); - - if (ncopies > 9) - memcpy (d, s, copysize); - - else - { - *(d + 0) = *(s + 0); - *(d + 1) = *(s + 1); - *(d + 2) = *(s + 2); - if (ncopies > 4) - { - *(d + 3) = *(s + 3); - *(d + 4) = *(s + 4); - if (ncopies > 6) - { - *(d + 5) = *(s + 5); - *(d + 6) = *(s + 6); - if (ncopies > 8) - { - *(d + 7) = *(s + 7); - *(d + 8) = *(s + 8); - } - } - } - } - + memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ); _int_free (av, oldp, 1); check_inuse_chunk (av, newp); return chunk2mem (newp); -- cgit 1.4.1 From a5bd0ba1926ecb6f6b4693921c60cdfca82e5c91 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Wed, 2 Jan 2019 16:46:12 +0100 Subject: intl: Do not return NULL on asprintf failure in gettext [BZ #24018] Fixes commit 9695dd0c9309712ed8e9c17a7040fe7af347f2dc ("DCIGETTEXT: Use getcwd, asprintf to construct absolute pathname"). (cherry picked from commit 8c1aafc1f34d090a5b41dc527c33e8687f6a1287) --- ChangeLog | 6 ++++++ NEWS | 1 + intl/dcigettext.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b5727c7585..4b18e27288 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019-01-02 Florian Weimer + + [BZ #24018] + * intl/dcigettext.c (DCIGETTEXT): Do not return NULL on asprintf + failure. + 2018-12-31 Florian Weimer [BZ #24027] diff --git a/NEWS b/NEWS index ef857b6e6c..49895f81bd 100644 --- a/NEWS +++ b/NEWS @@ -163,6 +163,7 @@ The following bugs are resolved with this release: [23579] libc: Errors misreported in preadv2 [23709] Fix CPU string flags for Haswell-type CPUs [23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591) + [24018] gettext may return NULL [24027] malloc: Integer overflow in realloc Version 2.26 diff --git a/intl/dcigettext.c b/intl/dcigettext.c index f63b34b0f5..cfcdd304b4 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -635,7 +635,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname); free (cwd); if (ret < 0) - return NULL; + goto return_untranslated; dirname = xdirname; } #ifndef IN_LIBGLOCALE -- cgit 1.4.1 From d851e9199e80ced73ee497339b6231950efbf785 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Fri, 15 Sep 2017 15:07:28 -0300 Subject: [BZ #21745] powerpc: build some IFUNC math functions for libc and libm Some math functions have to be distributed in libc because they're required by printf. libc and libm require their own builds of these functions, e.g. libc functions have to call __stack_chk_fail_local in order to bypass the PLT, while libm functions have to call __stack_chk_fail. While math/Makefile treat the generic cases, i.e. s_isinff, the multiarch Makefile has to treat its own files, i.e. s_isinff-ppc64. [BZ #21745] * sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile: [$(subdir) = math] (sysdep_calls): New variable. Has the previous contents of sysdep_routines, but re-sorted.. [$(subdir) = math] (sysdep_routines): Re-use the contents from sysdep_calls. [$(subdir) = math] (libm-sysdep_routines): Remove the functions defined in sysdep_calls and replace by the respective m_* names. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S: (compat_symbol): Undefine to avoid duplicated compat symbols in libc. (cherry picked from commit 61c45f250528dae431391823a9766053e61ccde1) --- ChangeLog | 14 +++++++++ sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile | 36 ++++++++++++---------- .../powerpc64/fpu/multiarch/s_isnan-ppc64.S | 3 ++ 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b18e27288..7d99754ec6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2019-01-11 Tulio Magno Quites Machado Filho + + [BZ #21745] + * sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile: + [$(subdir) = math] (sysdep_calls): New variable. Has the + previous contents of sysdep_routines, but re-sorted.. + [$(subdir) = math] (sysdep_routines): Re-use the contents from + sysdep_calls. + [$(subdir) = math] (libm-sysdep_routines): Remove the functions + defined in sysdep_calls and replace by the respective m_* names. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S: + (compat_symbol): Undefine to avoid duplicated compat symbols in + libc. + 2019-01-02 Florian Weimer [BZ #24018] diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile index d6f14f360a..73f2f69377 100644 --- a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile +++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile @@ -1,33 +1,35 @@ ifeq ($(subdir),math) -sysdep_routines += s_isnan-power7 s_isnan-power6x s_isnan-power6 \ - s_isnan-power5 s_isnan-ppc64 s_copysign-power6 \ - s_copysign-ppc64 s_finite-power7 s_finite-ppc64 \ - s_finitef-ppc64 s_isinff-ppc64 s_isinf-power7 \ - s_isinf-ppc64 s_modf-power5+ s_modf-ppc64 \ - s_modff-power5+ s_modff-ppc64 s_isnan-power8 \ - s_isinf-power8 s_finite-power8 +# These functions are built both for libc and libm because they're required +# by printf. While the libc objects have the prefix s_, the libm ones are +# prefixed with m_. +sysdep_calls := s_copysign-power6 s_copysign-ppc64 \ + s_finite-power8 s_finite-power7 s_finite-ppc64 \ + s_finitef-ppc64 \ + s_isinf-power8 s_isinf-ppc64 \ + s_isinff-ppc64 s_isinf-power7 \ + s_isnan-power8 s_isnan-power7 s_isnan-power6x s_isnan-power6 \ + s_isnan-power5 s_isnan-ppc64 \ + s_modf-power5+ s_modf-ppc64 \ + s_modff-power5+ s_modff-ppc64 -libm-sysdep_routines += s_isnan-power7 s_isnan-power6x s_isnan-power6 \ - s_isnan-power5 s_isnan-ppc64 s_llround-power6x \ +sysdep_routines += $(sysdep_calls) +libm-sysdep_routines += s_llround-power6x \ s_llround-power5+ s_llround-ppc64 s_ceil-power5+ \ s_ceil-ppc64 s_ceilf-power5+ s_ceilf-ppc64 \ s_floor-power5+ s_floor-ppc64 s_floorf-power5+ \ s_floorf-ppc64 s_round-power5+ s_round-ppc64 \ s_roundf-power5+ s_roundf-ppc64 s_trunc-power5+ \ s_trunc-ppc64 s_truncf-power5+ s_truncf-ppc64 \ - s_copysign-power6 s_copysign-ppc64 s_llrint-power6x \ - s_llrint-ppc64 s_finite-power7 s_finite-ppc64 \ - s_finitef-ppc64 s_isinff-ppc64 s_isinf-power7 \ - s_isinf-ppc64 s_logb-power7 s_logbf-power7 \ + s_llrint-power6x s_llrint-ppc64 \ + s_logb-power7 s_logbf-power7 \ s_logbl-power7 s_logb-ppc64 s_logbf-ppc64 \ - s_logbl-ppc64 s_modf-power5+ s_modf-ppc64 \ - s_modff-power5+ s_modff-ppc64 e_hypot-ppc64 \ + s_logbl-ppc64 e_hypot-ppc64 \ e_hypot-power7 e_hypotf-ppc64 e_hypotf-power7 \ - s_isnan-power8 s_isinf-power8 s_finite-power8 \ s_llrint-power8 s_llround-power8 s_llroundf-ppc64 \ e_expf-power8 e_expf-ppc64 \ s_sinf-ppc64 s_sinf-power8 \ - s_cosf-ppc64 s_cosf-power8 + s_cosf-ppc64 s_cosf-power8 \ + $(sysdep_calls:s_%=m_%) CFLAGS-s_logbf-power7.c = -mcpu=power7 CFLAGS-s_logbl-power7.c = -mcpu=power7 diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S index ee219c14be..eba0d4ff5e 100644 --- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S +++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan-ppc64.S @@ -23,6 +23,9 @@ #define weak_alias(a,b) #undef strong_alias #define strong_alias(a,b) +#undef compat_symbol +#define compat_symbol(a,b,c,d) + #define __isnan __isnan_ppc64 #undef hidden_def -- cgit 1.4.1 From 7ab39c6a3cd4a61a2be3d2e6a2a56f4dccca9750 Mon Sep 17 00:00:00 2001 From: "Gabriel F. T. Gomes" Date: Fri, 17 Nov 2017 18:20:42 -0200 Subject: powerpc: Regenerate ULPs On POWER9, cbrtf128 fails by 1 ULP. * sysdeps/powerpc/fpu/libm-test-ulps: Regenerate. Reviewed-by: Tulio Magno Quites Machado Filho (cherry picked from commit 428fc49eaafe0fe5352445fcf23d9f603e9083a2) --- ChangeLog | 4 ++++ sysdeps/powerpc/fpu/libm-test-ulps | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d99754ec6..60b0364037 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2019-01-11 Gabriel F. T. Gomes + + * sysdeps/powerpc/fpu/libm-test-ulps: Regenerate. + 2019-01-11 Tulio Magno Quites Machado Filho [BZ #21745] diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps index 7fb67446a5..117c7adb6f 100644 --- a/sysdeps/powerpc/fpu/libm-test-ulps +++ b/sysdeps/powerpc/fpu/libm-test-ulps @@ -860,10 +860,10 @@ ldouble: 3 Function: "cbrt_upward": double: 5 float: 1 -float128: 1 +float128: 2 idouble: 5 ifloat: 1 -ifloat128: 1 +ifloat128: 2 ildouble: 2 ldouble: 2 -- cgit 1.4.1