aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>2019-06-27 10:48:22 -0300
committerTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>2019-06-27 10:48:22 -0300
commit22f3c11df1c4dec1ec5310b29f29572805526625 (patch)
treedd0447cf95970792d2d58f0a76cf9234cd3b6686
parent0d1d7fb843ade0471f55fc8cbd17938d2f7b2335 (diff)
parent91b02c5b4d17d60015af24d277eb31348fc0bc34 (diff)
downloadglibc-22f3c11df1c4dec1ec5310b29f29572805526625.tar
glibc-22f3c11df1c4dec1ec5310b29f29572805526625.tar.gz
glibc-22f3c11df1c4dec1ec5310b29f29572805526625.tar.bz2
glibc-22f3c11df1c4dec1ec5310b29f29572805526625.zip
Merge branch release/2.28/master into ibm/2.28/master
-rw-r--r--ChangeLog92
-rw-r--r--NEWS13
-rw-r--r--dlfcn/dlerror.c29
-rw-r--r--elf/pldd-xx.c114
-rw-r--r--elf/pldd.c64
-rw-r--r--libio/Makefile18
-rw-r--r--libio/genops.c16
-rw-r--r--libio/tst-bz24228.c29
-rw-r--r--libio/tst-bz24228.map5
-rw-r--r--libio/tst-wfile-sync.c39
-rw-r--r--libio/tst-wfile-sync.input1
-rw-r--r--libio/wfileops.c5
-rw-r--r--localedata/locales/ja_JP4
-rw-r--r--malloc/malloc.c32
-rw-r--r--manual/tunables.texi4
-rw-r--r--posix/regexec.c6
-rw-r--r--sysdeps/s390/dl-procinfo.h3
-rw-r--r--sysdeps/unix/sysv/linux/riscv/kernel-features.h5
18 files changed, 342 insertions, 137 deletions
diff --git a/ChangeLog b/ChangeLog
index 42fe0aeb1e..2c82b3063a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,95 @@
+2019-06-20 Dmitry V. Levin <ldv@altlinux.org>
+ Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24228]
+ * libio/genops.c (_IO_unbuffer_all)
+ [SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
+ buffers and access _IO_FILE_complete members of legacy libio streams.
+ * libio/tst-bz24228.c: New file.
+ * libio/tst-bz24228.map: Likewise.
+ * libio/Makefile [build-shared] (tests): Add tst-bz24228.
+ [build-shared] (generated): Add tst-bz24228.mtrace and
+ tst-bz24228.check.
+ [run-built-tests && build-shared] (tests-special): Add
+ $(objpfx)tst-bz24228-mem.out.
+ (LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
+ ($(objpfx)tst-bz24228-mem.out): New rule.
+
+2019-05-22 Wilco Dijkstra <wdijkstr@arm.com>
+
+ [BZ #24531]
+ * malloc/malloc.c (MAX_TCACHE_COUNT): New define.
+ (do_set_tcache_count): Only update if count is small enough.
+ * manual/tunables.texi (glibc.malloc.tcache_count): Document max value.
+
+2019-05-15 Mark Wielaard <mark@klomp.org>
+
+ [BZ#24476]
+ * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
+ __libc_once_get (once) and static_buf == NULL.
+ (__dlerror): Check we have a valid key, set result to static_buf
+ otherwise.
+
+2019-05-15 Andreas Schwab <schwab@suse.de>
+
+ [BZ #20568]
+ * libio/wfileops.c (_IO_wfile_sync): Correct last argument to
+ __codecvt_do_length.
+ * libio/Makefile (tests): Add tst-wfile-sync.
+ ($(objpfx)tst-wfile-sync.out): Depend on $(gen-locales).
+ * libio/tst-wfile-sync.c: New file.
+ * libio/tst-wfile-sync.input: New file.
+
+2018-12-21 Istvan Kurucsai <pistukem@gmail.com>
+
+ * malloc/malloc.c (munmap_chunk): Verify chunk alignment.
+
+2018-12-20 Istvan Kurucsai <pistukem@gmail.com>
+
+ * malloc/malloc.c (mremap_chunk): Additional checks.
+
+2018-08-17 Istvan Kurucsai <pistukem@gmail.com>
+
+ * malloc/malloc.c (_int_malloc): Additional binning code checks.
+
+2019-04-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ #18035]
+ * elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
+ (E(find_maps)): Avoid use alloca, use default read file operations
+ instead of explicit LFS names, and fix infinite loop.
+ * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
+ (get_process_info): Use _Static_assert instead of assert, use default
+ directory operations instead of explicit LFS names, and free some
+ leadek pointers.
+
+2019-04-03 TAMUKI Shoichi <tamuki@linet.gr.jp>
+
+ [BZ #22964]
+ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese
+ era.
+
+2019-03-21 Stefan Liebler <stli@linux.ibm.com>
+
+ * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
+ Add HWCAP_S390_VX and HWCAP_S390_VXE.
+
+2019-01-31 Paul Eggert <eggert@cs.ucla.edu>
+
+ CVE-2019-9169
+ regex: fix read overrun [BZ #24114]
+ Problem found by AddressSanitizer, reported by Hongxu Chen in:
+ https://debbugs.gnu.org/34140
+ * posix/regexec.c (proceed_next_node):
+ Do not read past end of input buffer.
+
+2018-11-07 Andreas Schwab <schwab@suse.de>
+
+ [BZ #23864]
+ * sysdeps/unix/sysv/linux/riscv/kernel-features.h
+ (__ASSUME_SET_ROBUST_LIST) [__LINUX_KERNEL_VERSION < 0x041400]:
+ Undef.
+
2018-09-21 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* NEWS: Add note about new TLE support on powerpc64le.
diff --git a/NEWS b/NEWS
index 60b15116d6..0f1bff99e8 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ using `glibc' in the "product" field.
Version 2.28.1
+Major new features:
+
+* The entry for the new Japanese era has been added for ja_JP locale.
+
Deprecated and removed features, and other changes affecting compatibility:
* For powercp64le ABI, Transactional Lock Elision is now enabled iff kernel
@@ -20,9 +24,11 @@ Deprecated and removed features, and other changes affecting compatibility:
The following bugs are resolved with this release:
+ [18035] Fix pldd hang
[19444] build failures with -O1 due to -Wmaybe-uninitialized
[20018] getaddrinfo should reject IP addresses with trailing characters
[20209] localedata: Spelling mistake for Sunday in Greenlandic kl_GL
+ [20568] Fix crash in _IO_wfile_sync
[22927] libanl: properly cleanup if first helper thread creation failed
[23400] stdlib/test-bz22786.c creates temporary files in glibc source tree
[23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream
@@ -39,6 +45,7 @@ The following bugs are resolved with this release:
[23717] Fix stack overflow in stdlib/tst-setcontext9
[23821] si_band in siginfo_t has wrong type long int on sparc64
[23822] ia64 static libm.a is missing exp2f, log2f and powf symbols
+ [23864] libc: [riscv] missing kernel-features.h undefines
[23844] pthread_rwlock_trywrlock results in hang
[23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591)
[23972] __old_getdents64 uses wrong d_off value on overflow
@@ -51,6 +58,8 @@ The following bugs are resolved with this release:
[24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488)
[24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
[24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
+ [24228] old x86 applications that use legacy libio crash on exit
+ [24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once)
Security related changes:
@@ -75,6 +84,10 @@ Security related changes:
CVE-2016-10739: The getaddrinfo function could successfully parse IPv4
addresses with arbitrary trailing characters, potentially leading to data
or command injection issues in applications.
+
+ CVE-2019-9169: Attempted case-insensitive regular-expression match
+ via proceed_next_node in posix/regexec.c leads to heap-based buffer
+ over-read. Reported by Hongxu Chen.
Version 2.28
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
index 96bf925333..06732460ea 100644
--- a/dlfcn/dlerror.c
+++ b/dlfcn/dlerror.c
@@ -72,9 +72,16 @@ __dlerror (void)
__libc_once (once, init);
/* Get error string. */
- result = (struct dl_action_result *) __libc_getspecific (key);
- if (result == NULL)
- result = &last_result;
+ if (static_buf != NULL)
+ result = static_buf;
+ else
+ {
+ /* init () has been run and we don't use the static buffer.
+ So we have a valid key. */
+ result = (struct dl_action_result *) __libc_getspecific (key);
+ if (result == NULL)
+ result = &last_result;
+ }
/* Test whether we already returned the string. */
if (result->returned != 0)
@@ -230,13 +237,19 @@ free_key_mem (void *mem)
void
__dlerror_main_freeres (void)
{
- void *mem;
/* Free the global memory if used. */
check_free (&last_result);
- /* Free the TSD memory if used. */
- mem = __libc_getspecific (key);
- if (mem != NULL)
- free_key_mem (mem);
+
+ if (__libc_once_get (once) && static_buf == NULL)
+ {
+ /* init () has been run and we don't use the static buffer.
+ So we have a valid key. */
+ void *mem;
+ /* Free the TSD memory if used. */
+ mem = __libc_getspecific (key);
+ if (mem != NULL)
+ free_key_mem (mem);
+ }
}
struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c
index 2823dea662..f818d98582 100644
--- a/elf/pldd-xx.c
+++ b/elf/pldd-xx.c
@@ -23,10 +23,6 @@
#define EW_(e, w, t) EW__(e, w, _##t)
#define EW__(e, w, t) e##w##t
-#define pldd_assert(name, exp) \
- typedef int __assert_##name[((exp) != 0) - 1]
-
-
struct E(link_map)
{
EW(Addr) l_addr;
@@ -39,12 +35,12 @@ struct E(link_map)
EW(Addr) l_libname;
};
#if CLASS == __ELF_NATIVE_CLASS
-pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
- == offsetof (struct E(link_map), l_addr)));
-pldd_assert (l_name, (offsetof (struct link_map, l_name)
- == offsetof (struct E(link_map), l_name)));
-pldd_assert (l_next, (offsetof (struct link_map, l_next)
- == offsetof (struct E(link_map), l_next)));
+_Static_assert (offsetof (struct link_map, l_addr)
+ == offsetof (struct E(link_map), l_addr), "l_addr");
+_Static_assert (offsetof (struct link_map, l_name)
+ == offsetof (struct E(link_map), l_name), "l_name");
+_Static_assert (offsetof (struct link_map, l_next)
+ == offsetof (struct E(link_map), l_next), "l_next");
#endif
@@ -54,10 +50,10 @@ struct E(libname_list)
EW(Addr) next;
};
#if CLASS == __ELF_NATIVE_CLASS
-pldd_assert (name, (offsetof (struct libname_list, name)
- == offsetof (struct E(libname_list), name)));
-pldd_assert (next, (offsetof (struct libname_list, next)
- == offsetof (struct E(libname_list), next)));
+_Static_assert (offsetof (struct libname_list, name)
+ == offsetof (struct E(libname_list), name), "name");
+_Static_assert (offsetof (struct libname_list, next)
+ == offsetof (struct E(libname_list), next), "next");
#endif
struct E(r_debug)
@@ -69,16 +65,17 @@ struct E(r_debug)
EW(Addr) r_map;
};
#if CLASS == __ELF_NATIVE_CLASS
-pldd_assert (r_version, (offsetof (struct r_debug, r_version)
- == offsetof (struct E(r_debug), r_version)));
-pldd_assert (r_map, (offsetof (struct r_debug, r_map)
- == offsetof (struct E(r_debug), r_map)));
+_Static_assert (offsetof (struct r_debug, r_version)
+ == offsetof (struct E(r_debug), r_version), "r_version");
+_Static_assert (offsetof (struct r_debug, r_map)
+ == offsetof (struct E(r_debug), r_map), "r_map");
#endif
static int
-E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
+E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
+ size_t auxv_size)
{
EW(Addr) phdr = 0;
unsigned int phnum = 0;
@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (phdr == 0 || phnum == 0 || phent == 0)
error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
- EW(Phdr) *p = alloca (phnum * phent);
- if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
- {
- error (0, 0, gettext ("cannot read program header"));
- return EXIT_FAILURE;
- }
+ EW(Phdr) *p = xmalloc (phnum * phent);
+ if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
+ error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
/* Determine the load offset. We need this for interpreting the
other program header entries so we do this in a separate loop.
@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (p[i].p_type == PT_DYNAMIC)
{
EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
- if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
+ if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
- {
- error (0, 0, gettext ("cannot read dynamic section"));
- return EXIT_FAILURE;
- }
+ error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
/* Search for the DT_DEBUG entry. */
for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
{
struct E(r_debug) r;
- if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
+ if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
!= sizeof (r))
- {
- error (0, 0, gettext ("cannot read r_debug"));
- return EXIT_FAILURE;
- }
+ error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
if (r.r_map != 0)
{
@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
else if (p[i].p_type == PT_INTERP)
{
- interp = alloca (p[i].p_filesz);
- if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
+ interp = xmalloc (p[i].p_filesz);
+ if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
- {
- error (0, 0, gettext ("cannot read program interpreter"));
- return EXIT_FAILURE;
- }
+ error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
}
if (list == 0)
@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (interp == NULL)
{
// XXX check whether the executable itself is the loader
- return EXIT_FAILURE;
+ exit (EXIT_FAILURE);
}
// XXX perhaps try finding ld.so and _r_debug in it
-
- return EXIT_FAILURE;
+ exit (EXIT_FAILURE);
}
+ free (p);
+ free (interp);
+
/* Print the PID and program name first. */
printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
do
{
struct E(link_map) m;
- if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
- {
- error (0, 0, gettext ("cannot read link map"));
- status = EXIT_FAILURE;
- goto out;
- }
+ if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
+ error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
EW(Addr) name_offset = m.l_name;
- again:
while (1)
{
- ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
+ ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
if (n == -1)
- {
- error (0, 0, gettext ("cannot read object name"));
- status = EXIT_FAILURE;
- goto out;
- }
+ error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
if (memchr (tmpbuf.data, '\0', n) != NULL)
break;
if (!scratch_buffer_grow (&tmpbuf))
- {
- error (0, 0, gettext ("cannot allocate buffer for object name"));
- status = EXIT_FAILURE;
- goto out;
- }
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot allocate buffer for object name"));
}
- if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
- && m.l_libname != 0)
- {
- /* Try the l_libname element. */
- struct E(libname_list) ln;
- if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
- {
- name_offset = ln.name;
- goto again;
- }
- }
+ /* The m.l_name and m.l_libname.name for loader linkmap points to same
+ values (since BZ#387 fix). Trying to use l_libname name as the
+ shared object name might lead to an infinite loop (BZ#18035). */
/* Skip over the executable. */
if (((char *)tmpbuf.data)[0] != '\0')
@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
while (list != 0);
- out:
scratch_buffer_free (&tmpbuf);
return status;
}
diff --git a/elf/pldd.c b/elf/pldd.c
index b8106fdc33..0bdfff450a 100644
--- a/elf/pldd.c
+++ b/elf/pldd.c
@@ -17,23 +17,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <alloca.h>
+#define _FILE_OFFSET_BITS 64
+
#include <argp.h>
-#include <assert.h>
#include <dirent.h>
-#include <elf.h>
-#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <libintl.h>
-#include <link.h>
-#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
-#include <sys/stat.h>
#include <sys/wait.h>
#include <scratch_buffer.h>
@@ -76,14 +70,9 @@ static struct argp argp =
options, parse_opt, args_doc, doc, NULL, more_help, NULL
};
-// File descriptor of /proc/*/mem file.
-static int memfd;
-
-/* Name of the executable */
-static char *exe;
/* Local functions. */
-static int get_process_info (int dfd, long int pid);
+static int get_process_info (const char *exe, int dfd, long int pid);
static void wait_for_ptrace_stop (long int pid);
@@ -102,8 +91,10 @@ main (int argc, char *argv[])
return 1;
}
- assert (sizeof (pid_t) == sizeof (int)
- || sizeof (pid_t) == sizeof (long int));
+ _Static_assert (sizeof (pid_t) == sizeof (int)
+ || sizeof (pid_t) == sizeof (long int),
+ "sizeof (pid_t) != sizeof (int) or sizeof (long int)");
+
char *endp;
errno = 0;
long int pid = strtol (argv[remaining], &endp, 10);
@@ -119,25 +110,24 @@ main (int argc, char *argv[])
if (dfd == -1)
error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
- struct scratch_buffer exebuf;
- scratch_buffer_init (&exebuf);
+ /* Name of the executable */
+ struct scratch_buffer exe;
+ scratch_buffer_init (&exe);
ssize_t nexe;
while ((nexe = readlinkat (dfd, "exe",
- exebuf.data, exebuf.length)) == exebuf.length)
+ exe.data, exe.length)) == exe.length)
{
- if (!scratch_buffer_grow (&exebuf))
+ if (!scratch_buffer_grow (&exe))
{
nexe = -1;
break;
}
}
if (nexe == -1)
- exe = (char *) "<program name undetermined>";
+ /* Default stack allocation is at least 1024. */
+ snprintf (exe.data, exe.length, "<program name undetermined>");
else
- {
- exe = exebuf.data;
- exe[nexe] = '\0';
- }
+ ((char*)exe.data)[nexe] = '\0';
/* Stop all threads since otherwise the list of loaded modules might
change while we are reading it. */
@@ -155,8 +145,8 @@ main (int argc, char *argv[])
error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
buf);
- struct dirent64 *d;
- while ((d = readdir64 (dir)) != NULL)
+ struct dirent *d;
+ while ((d = readdir (dir)) != NULL)
{
if (! isdigit (d->d_name[0]))
continue;
@@ -182,7 +172,7 @@ main (int argc, char *argv[])
wait_for_ptrace_stop (tid);
- struct thread_list *newp = alloca (sizeof (*newp));
+ struct thread_list *newp = xmalloc (sizeof (*newp));
newp->tid = tid;
newp->next = thread_list;
thread_list = newp;
@@ -190,17 +180,22 @@ main (int argc, char *argv[])
closedir (dir);
- int status = get_process_info (dfd, pid);
+ if (thread_list == NULL)
+ error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf);
+
+ int status = get_process_info (exe.data, dfd, pid);
- assert (thread_list != NULL);
do
{
ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
+ struct thread_list *prev = thread_list;
thread_list = thread_list->next;
+ free (prev);
}
while (thread_list != NULL);
close (dfd);
+ scratch_buffer_free (&exe);
return status;
}
@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
static int
-get_process_info (int dfd, long int pid)
+get_process_info (const char *exe, int dfd, long int pid)
{
- memfd = openat (dfd, "mem", O_RDONLY);
+ /* File descriptor of /proc/<pid>/mem file. */
+ int memfd = openat (dfd, "mem", O_RDONLY);
if (memfd == -1)
goto no_info;
@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid)
int retval;
if (e_ident[EI_CLASS] == ELFCLASS32)
- retval = find_maps32 (pid, auxv, auxv_size);
+ retval = find_maps32 (exe, memfd, pid, auxv, auxv_size);
else
- retval = find_maps64 (pid, auxv, auxv_size);
+ retval = find_maps64 (exe, memfd, pid, auxv, auxv_size);
free (auxv);
close (memfd);
diff --git a/libio/Makefile b/libio/Makefile
index cab0eae946..314e03d5ce 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -64,7 +64,8 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
bug-memstream1 bug-wmemstream1 \
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 tst-bz22415 tst-fgetc-after-eof
+ tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
+ tst-wfile-sync
tests-internal = tst-vtables tst-vtables-interposed tst-readline
@@ -72,6 +73,9 @@ ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
tests += tst-fopenloc
+# Add tst-bz24228 only if shared library is enabled since it can never meet its
+# objective with static linking because the relevant code just is not there.
+tests += tst-bz24228
endif
test-srcs = test-freopen
@@ -152,11 +156,14 @@ CFLAGS-oldtmpfile.c += -fexceptions
CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
+LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
+
tst_wprintf2-ARGS = "Some Text"
test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
generated += test-fmemopen.mtrace test-fmemopen.check
generated += tst-fopenloc.mtrace tst-fopenloc.check
@@ -165,6 +172,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
aux := fileops genops stdfiles stdio strops
ifeq ($(build-shared),yes)
+generated += tst-bz24228.mtrace tst-bz24228.check
aux += oldfileops oldstdfiles
endif
@@ -179,7 +187,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
ifeq (yes,$(build-shared))
# Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
# library is enabled since they depend on tst-fopenloc.out.
-tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
+tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
+ $(objpfx)tst-bz24228-mem.out
endif
endif
@@ -207,6 +216,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales)
$(objpfx)tst-ungetwc2.out: $(gen-locales)
$(objpfx)tst-widetext.out: $(gen-locales)
$(objpfx)tst_wprintf2.out: $(gen-locales)
+$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
@@ -230,3 +240,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
$(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
$(evaluate-test)
+
+$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
+ $(evaluate-test)
diff --git a/libio/genops.c b/libio/genops.c
index 2fec221b99..a8241dd266 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
{
+ int legacy = 0;
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+ if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
+ legacy = 1;
+#endif
+
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
- && fp->_mode != 0)
+ && (legacy || fp->_mode != 0))
{
#ifdef _IO_MTSAFE_IO
int cnt;
@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
__sched_yield ();
#endif
- if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
+ if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
_IO_SETBUF (fp, NULL, 0);
- if (fp->_mode > 0)
+ if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
#ifdef _IO_MTSAFE_IO
@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
/* Make sure that never again the wide char functions can be
used. */
- fp->_mode = -1;
+ if (! legacy)
+ fp->_mode = -1;
}
#ifdef _IO_MTSAFE_IO
diff --git a/libio/tst-bz24228.c b/libio/tst-bz24228.c
new file mode 100644
index 0000000000..6a74500d47
--- /dev/null
+++ b/libio/tst-bz24228.c
@@ -0,0 +1,29 @@
+/* BZ #24228 check for memory corruption in legacy libio
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <mcheck.h>
+#include <support/test-driver.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map
new file mode 100644
index 0000000000..4383e0817d
--- /dev/null
+++ b/libio/tst-bz24228.map
@@ -0,0 +1,5 @@
+# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
+# implementation when it is available for the architecture.
+{
+ local: _IO_stdin_used;
+};
diff --git a/libio/tst-wfile-sync.c b/libio/tst-wfile-sync.c
new file mode 100644
index 0000000000..618682064d
--- /dev/null
+++ b/libio/tst-wfile-sync.c
@@ -0,0 +1,39 @@
+/* Test that _IO_wfile_sync does not crash (bug 20568).
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+
+static int
+do_test (void)
+{
+ TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
+ /* Fill the stdio buffer and advance the read pointer. */
+ TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
+ /* This calls _IO_wfile_sync, it should not crash. */
+ TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
+ /* Verify that the external file offset has been synchronized. */
+ TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/libio/tst-wfile-sync.input b/libio/tst-wfile-sync.input
new file mode 100644
index 0000000000..12d0958f7a
--- /dev/null
+++ b/libio/tst-wfile-sync.input
@@ -0,0 +1 @@
+This is a test of _IO_wfile_sync.
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 63cb687652..10e7343f8f 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -508,11 +508,12 @@ _IO_wfile_sync (FILE *fp)
generate the wide characters up to the current reading
position. */
int nread;
-
+ size_t wnread = (fp->_wide_data->_IO_read_ptr
+ - fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
fp->_IO_read_base,
- fp->_IO_read_end, delta);
+ fp->_IO_read_end, wnread);
fp->_IO_read_ptr = fp->_IO_read_base + nread;
delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
}
diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP
index 1fd2fee44b..30190b6248 100644
--- a/localedata/locales/ja_JP
+++ b/localedata/locales/ja_JP
@@ -14946,7 +14946,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 27cf6137c2..0e7970001a 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2810,6 +2810,7 @@ systrim (size_t pad, mstate av)
static void
munmap_chunk (mchunkptr p)
{
+ size_t pagesize = GLRO (dl_pagesize);
INTERNAL_SIZE_T size = chunksize (p);
assert (chunk_is_mmapped (p));
@@ -2819,6 +2820,7 @@ munmap_chunk (mchunkptr p)
if (DUMPED_MAIN_ARENA_CHUNK (p))
return;
+ uintptr_t mem = (uintptr_t) chunk2mem (p);
uintptr_t block = (uintptr_t) p - prev_size (p);
size_t total_size = prev_size (p) + size;
/* Unfortunately we have to do the compilers job by hand here. Normally
@@ -2826,7 +2828,8 @@ munmap_chunk (mchunkptr p)
page size. But gcc does not recognize the optimization possibility
(in the moment at least) so we combine the two values into one before
the bit test. */
- if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0))
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
malloc_printerr ("munmap_chunk(): invalid pointer");
atomic_decrement (&mp_.n_mmaps);
@@ -2849,16 +2852,22 @@ mremap_chunk (mchunkptr p, size_t new_size)
char *cp;
assert (chunk_is_mmapped (p));
- assert (((size + offset) & (GLRO (dl_pagesize) - 1)) == 0);
+
+ uintptr_t block = (uintptr_t) p - offset;
+ uintptr_t mem = (uintptr_t) chunk2mem(p);
+ size_t total_size = offset + size;
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
+ malloc_printerr("mremap_chunk(): invalid pointer");
/* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
new_size = ALIGN_UP (new_size + offset + SIZE_SZ, pagesize);
/* No need to remap if the number of pages does not change. */
- if (size + offset == new_size)
+ if (total_size == new_size)
return p;
- cp = (char *) __mremap ((char *) p - offset, size + offset, new_size,
+ cp = (char *) __mremap ((char *) block, total_size, new_size,
MREMAP_MAYMOVE);
if (cp == MAP_FAILED)
@@ -2903,6 +2912,8 @@ typedef struct tcache_perthread_struct
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
+#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
+
static __thread bool tcache_shutting_down = false;
static __thread tcache_perthread_struct *tcache = NULL;
@@ -3738,7 +3749,7 @@ _int_malloc (mstate av, size_t bytes)
if (__glibc_unlikely (bck->fd != victim)
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
malloc_printerr ("malloc(): unsorted double linked list corrupted");
- if (__glibc_unlikely (prev_inuse(next)))
+ if (__glibc_unlikely (prev_inuse (next)))
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
/*
@@ -3860,10 +3871,14 @@ _int_malloc (mstate av, size_t bytes)
{
victim->fd_nextsize = fwd;
victim->bk_nextsize = fwd->bk_nextsize;
+ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
+ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
fwd->bk_nextsize = victim;
victim->bk_nextsize->fd_nextsize = victim;
}
bck = fwd->bk;
+ if (bck->fd != fwd)
+ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
}
}
else
@@ -5109,8 +5124,11 @@ static inline int
__always_inline
do_set_tcache_count (size_t value)
{
- LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
- mp_.tcache_count = value;
+ if (value <= MAX_TCACHE_COUNT)
+ {
+ LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
+ mp_.tcache_count = value;
+ }
return 1;
}
diff --git a/manual/tunables.texi b/manual/tunables.texi
index bb4819bdf1..9dccf2ee7f 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -188,8 +188,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
@deftp Tunable glibc.malloc.tcache_count
The maximum number of chunks of each size to cache. The default is 7.
-There is no upper limit, other than available system memory. If set
-to zero, the per-thread cache is effectively disabled.
+The upper limit is 127. If set to zero, the per-thread cache is effectively
+disabled.
The approximate maximum overhead of the per-thread cache is thus equal
to the number of bins times the chunk count in each bin times the size
diff --git a/posix/regexec.c b/posix/regexec.c
index 73644c2341..06b8487c3e 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -1289,8 +1289,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
else if (naccepted)
{
char *buf = (char *) re_string_get_buffer (&mctx->input);
- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
- naccepted) != 0)
+ if (mctx->input.valid_len - *pidx < naccepted
+ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
+ naccepted)
+ != 0))
return -1;
}
}
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
index b0383bfb4c..f71d64c3ab 100644
--- a/sysdeps/s390/dl-procinfo.h
+++ b/sysdeps/s390/dl-procinfo.h
@@ -57,7 +57,8 @@ enum
};
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
- | HWCAP_S390_EIMM | HWCAP_S390_DFP)
+ | HWCAP_S390_EIMM | HWCAP_S390_DFP \
+ | HWCAP_S390_VX | HWCAP_S390_VXE)
/* We cannot provide a general printing function. */
#define _dl_procinfo(type, word) -1
diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
index 37f4d99a92..d21c824624 100644
--- a/sysdeps/unix/sysv/linux/riscv/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
@@ -21,3 +21,8 @@
#undef __ASSUME_CLONE_DEFAULT
#define __ASSUME_CLONE_BACKWARDS 1
+
+/* No support for PI mutexes or robust futexes before 4.20. */
+#if __LINUX_KERNEL_VERSION < 0x041400
+# undef __ASSUME_SET_ROBUST_LIST
+#endif