From f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 15 May 2011 00:34:48 -0400 Subject: [PATCH] Use mmap for allocation of buffers used for __abort_msg --- ChangeLog | 18 ++++++++++ NEWS | 12 +++---- assert/assert-perr.c | 54 ++++------------------------ assert/assert.c | 51 +++++++++++++++++++------- include/assert.h | 8 ++++- include/stdlib.h | 11 ++++-- stdlib/abort.c | 5 +-- sysdeps/posix/libc_fatal.c | 33 +++++++++++------ sysdeps/unix/sysv/linux/libc_fatal.c | 34 ++++++++++++------ 9 files changed, 131 insertions(+), 95 deletions(-) diff --git a/ChangeLog b/ChangeLog index a11ee6cc21..08f1c06fd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ +2011-05-15 Ulrich Drepper + + [BZ #11901] + * include/stdlib.h: Move include protection to the right place. + Define abort_msg_s. Declare __abort_msg with it. + * stdlib/abort.c (__abort_msg): Adjust type. + * assert/assert.c (__assert_fail_base): New function. Majority + of code from __assert_fail. Allocate memory for __abort_msg with + mmap. + (__assert_fail): Now call __assert_fail_base. + * assert/assert-perr.c: Remove bulk of implementation. Use + __assert_fail_base. + * include/assert.hL Declare __assert_fail_base. + * sysdeps/posix/libc_fatal.c: Allocate memory for __abort_msg with + mmap. + * sysdeps/unix/sysv/linux/libc_fatal.c: Likewise. + 2011-05-14 Ulrich Drepper + [BZ #11952] [BZ #12453] * elf/dl-open.c (dl_open_worker): Delay calls to _dl_update_slotinfo until all modules are registered in the DTV. diff --git a/NEWS b/NEWS index 891207b50d..5a120e76e2 100644 --- a/NEWS +++ b/NEWS @@ -9,12 +9,12 @@ Version 2.14 * The following bugs are resolved with this release: - 386, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11945, 11947, - 11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, - 12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, - 12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, - 12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, - 12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738 + 386, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11901, 11945, + 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420, + 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510, + 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597, + 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681, + 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738 * The RPC implementation in libc is obsoleted. Old programs keep working but new programs cannot be linked with the routines in libc anymore. diff --git a/assert/assert-perr.c b/assert/assert-perr.c index f239fab86b..cad87dab0d 100644 --- a/assert/assert-perr.c +++ b/assert/assert-perr.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1994-1998,2001,2002,2005,2009 Free Software Foundation, Inc. +/* Copyright (C) 1994-1998,2001,2002,2005,2009,2011 + 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 @@ -17,66 +18,23 @@ 02111-1307 USA. */ #include -#include #include -#include -#include #include -#include -#include -extern const char *__progname; - -#ifdef USE_IN_LIBIO -# include -# include -# define fflush(s) INTUSE(_IO_fflush) (s) -#endif - /* This function, when passed an error number, a filename, and a line number, prints a message on the standard error stream of the form: - a.c:10: foobar: Unexpected error: Computer bought the farm + a.c:10: foobar: Unexpected error: Computer bought the farm It then aborts program execution via a call to `abort'. */ - -#ifdef FATAL_PREPARE_INCLUDE -# include FATAL_PREPARE_INCLUDE -#endif - void __assert_perror_fail (int errnum, const char *file, unsigned int line, const char *function) { char errbuf[1024]; - char *buf; -#ifdef FATAL_PREPARE - FATAL_PREPARE; -#endif - - if (__asprintf (&buf, _("%s%s%s:%u: %s%sUnexpected error: %s.\n"), - __progname, __progname[0] ? ": " : "", - file, line, - function ? function : "", function ? ": " : "", - __strerror_r (errnum, errbuf, sizeof errbuf)) >= 0) - { - /* Print the message. */ - (void) __fxprintf (NULL, "%s", buf); - (void) fflush (stderr); - - /* We have to free the old buffer since the application might - catch the SIGABRT signal. */ - char *old = atomic_exchange_acq (&__abort_msg, buf); - free (old); - } - else - { - /* At least print a minimal message. */ - static const char errstr[] = "Unexpected error.\n"; - __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); - } - - abort (); + char *e = __strerror_r (errnum, errbuf, sizeof errbuf); + __assert_fail_base (_("%s%s%s:%u: %s%sUnexpected error: %s.\n"), + e, file, line, function); } libc_hidden_def (__assert_perror_fail) diff --git a/assert/assert.c b/assert/assert.c index 727fb1446c..803015f0f4 100644 --- a/assert/assert.c +++ b/assert/assert.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,1994-1996,1998,2001,2002,2005,2009 +/* Copyright (C) 1991,1994-1996,1998,2001,2002,2005,2009,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -19,11 +19,13 @@ #include #include +#include #include #include #include #include #include +#include extern const char *__progname; @@ -37,7 +39,7 @@ extern const char *__progname; /* This function, when passed a string containing an asserted expression, a filename, and a line number, prints a message on the standard error stream of the form: - a.c:10: foobar: Assertion `a == b' failed. + a.c:10: foobar: Assertion `a == b' failed. It then aborts program execution via a call to `abort'. */ #ifdef FATAL_PREPARE_INCLUDE @@ -45,31 +47,44 @@ extern const char *__progname; #endif -#undef __assert_fail void -__assert_fail (const char *assertion, const char *file, unsigned int line, - const char *function) +__assert_fail_base (const char *fmt, const char *assertion, const char *file, + unsigned int line, const char *function) { - char *buf; + char *str; #ifdef FATAL_PREPARE FATAL_PREPARE; #endif - if (__asprintf (&buf, _("%s%s%s:%u: %s%sAssertion `%s' failed.\n"), + int total; + if (__asprintf (&str, fmt, __progname, __progname[0] ? ": " : "", file, line, function ? function : "", function ? ": " : "", - assertion) >= 0) + assertion, &total) >= 0) { /* Print the message. */ - (void) __fxprintf (NULL, "%s", buf); + (void) __fxprintf (NULL, "%s", str); (void) fflush (stderr); - /* We have to free the old buffer since the application might - catch the SIGABRT signal. */ - char *old = atomic_exchange_acq (&__abort_msg, buf); - free (old); + total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); + struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (__builtin_expect (buf != MAP_FAILED, 1)) + { + buf->size = total; + strcpy (buf->msg, str); + + /* We have to free the old buffer since the application might + catch the SIGABRT signal. */ + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, buf); + + if (old != NULL) + __munmap (old, old->size); + } + + free (str); } else { @@ -80,4 +95,14 @@ __assert_fail (const char *assertion, const char *file, unsigned int line, abort (); } + + +#undef __assert_fail +void +__assert_fail (const char *assertion, const char *file, unsigned int line, + const char *function) +{ + __assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"), + assertion, file, line, function); +} hidden_def(__assert_fail) diff --git a/include/assert.h b/include/assert.h index b53313de8f..4b022342ef 100644 --- a/include/assert.h +++ b/include/assert.h @@ -5,7 +5,7 @@ so it has to be repeated here. */ extern void __assert_fail (__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) - __THROW __attribute__ ((__noreturn__)); + __THROW __attribute__ ((__noreturn__)); /* Likewise, but prints the error text for ERRNUM. */ extern void __assert_perror_fail (int __errnum, __const char *__file, @@ -13,6 +13,12 @@ extern void __assert_perror_fail (int __errnum, __const char *__file, __const char *__function) __THROW __attribute__ ((__noreturn__)); +/* The real implementation of the two functions above. */ +extern void __assert_fail_base (const char *fmt, const char *assertion, + const char *file, unsigned int line, + const char *function) + __THROW __attribute__ ((__noreturn__)); + #if !defined NOT_IN_libc || defined IS_IN_rtld hidden_proto (__assert_fail) hidden_proto (__assert_perror_fail) diff --git a/include/stdlib.h b/include/stdlib.h index b4799d7d04..816f8ffc2e 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -223,16 +223,21 @@ extern int __qfcvt_r (long double __value, int __ndigit, # define __cxa_atexit(func, arg, d) INTUSE(__cxa_atexit) (func, arg, d) # endif -#endif - extern void *__default_morecore (ptrdiff_t) __THROW; libc_hidden_proto (__default_morecore) -extern char *__abort_msg; +struct abort_msg_s +{ + unsigned int size; + char msg[0]; +}; +extern struct abort_msg_s *__abort_msg; libc_hidden_proto (__abort_msg) __END_DECLS +#endif + #undef __Need_M_And_C #endif /* include/stdlib.h */ diff --git a/stdlib/abort.c b/stdlib/abort.c index 3c188c9516..e9d0ab18fd 100644 --- a/stdlib/abort.c +++ b/stdlib/abort.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,93,1995-1998,2001,02,2009 Free Software Foundation, Inc. +/* Copyright (C) 1991,1993,1995-1998,2001,2002,2009,2011 + 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 @@ -37,7 +38,7 @@ #endif /* Exported variable to locate abort message in core files etc. */ -char *__abort_msg __attribute__ ((nocommon)); +struct abort_msg_s *__abort_msg __attribute__ ((nocommon)); libc_hidden_def (__abort_msg) /* We must avoid to run in circles. Therefore we remember how far we diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c index 4f11c0fcb0..f3847011fc 100644 --- a/sysdeps/posix/libc_fatal.c +++ b/sysdeps/posix/libc_fatal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-1995,1997,2000,2004,2005,2009 +/* Copyright (C) 1993-1995,1997,2000,2004,2005,2009,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -125,18 +126,28 @@ __libc_message (int do_abort, const char *fmt, ...) if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total) written = true; - char *buf = do_abort ? malloc (total + 1) : NULL; - if (buf != NULL) + if (do_abort) { - char *wp = buf; - for (int cnt = 0; cnt < nlist; ++cnt) - wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); - *wp = '\0'; + total = ((total + 1 + GLRO(dl_pagesize) - 1) + & ~(GLRO(dl_pagesize) - 1)); + struct abort_msg_s *buf = __mmap (NULL, total, + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (buf != MAP_FAILED) + { + buf->size = total; + char *wp = buf->msg; + for (int cnt = 0; cnt < nlist; ++cnt) + wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); + *wp = '\0'; - /* We have to free the old buffer since the application might - catch the SIGABRT signal. */ - char *old = atomic_exchange_acq (&__abort_msg, buf); - free (old); + /* We have to free the old buffer since the application might + catch the SIGABRT signal. */ + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, + buf); + if (old != NULL) + __munmap (old, old->size); + } } } diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c index 7287f4ef6c..e1b4c8d314 100644 --- a/sysdeps/unix/sysv/linux/libc_fatal.c +++ b/sysdeps/unix/sysv/linux/libc_fatal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009 +/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -134,18 +136,28 @@ __libc_message (int do_abort, const char *fmt, ...) if (cnt == total) written = true; - char *buf = do_abort ? malloc (total + 1) : NULL; - if (buf != NULL) + if (do_abort) { - char *wp = buf; - for (int cnt = 0; cnt < nlist; ++cnt) - wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); - *wp = '\0'; + total = ((total + 1 + GLRO(dl_pagesize) - 1) + & ~(GLRO(dl_pagesize) - 1)); + struct abort_msg_s *buf = __mmap (NULL, total, + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (__builtin_expect (buf != MAP_FAILED, 1)) + { + buf->size = total; + char *wp = buf->msg; + for (int cnt = 0; cnt < nlist; ++cnt) + wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); + *wp = '\0'; - /* We have to free the old buffer since the application might - catch the SIGABRT signal. */ - char *old = atomic_exchange_acq (&__abort_msg, buf); - free (old); + /* We have to free the old buffer since the application might + catch the SIGABRT signal. */ + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, + buf); + if (old != NULL) + __munmap (old, old->size); + } } }