malloc: Abort on heap corruption, without a backtrace [BZ #21754]

The stack trace printing caused deadlocks and has been itself been
targeted by code execution exploits.
This commit is contained in:
Florian Weimer 2017-08-30 16:39:41 +02:00
parent 9ce673b69e
commit ec2c1fcefb
5 changed files with 37 additions and 51 deletions

View File

@ -1,3 +1,12 @@
2017-08-30 Florian Weimer <fweimer@redhat.com>
[BZ #21754]
* malloc/malloc.c (malloc_printerr): Always terminate the process,
without printing a backtrace. Do not leak any information in the
error message.
* manual/memory.texi (Heap Consistency Checking): Update.
* manual/tunables.texi (Memory Allocation Tunables): Likewise.
2017-08-30 Florian Weimer <fweimer@redhat.com>
Do not scale NPTL tests with available number of CPUs.

8
NEWS
View File

@ -12,6 +12,14 @@ Major new features:
* Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan
with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel.
* In order to support faster and safer process termination the malloc API
family of functions will no longer print a failure address and stack
backtrace after detecting heap corruption. The goal is to minimize the
amount of work done after corruption is detected and to avoid potential
security issues in continued process execution. Reducing shutdown time
leads to lower overall process restart latency, so there is benefit both
from a security and performance perspective.
Deprecated and removed features, and other changes affecting compatibility:
* On GNU/Linux, the obsolete Linux constant PTRACE_SEIZE_DEVEL is no longer

View File

@ -1019,7 +1019,8 @@ static void* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T,
static void* _int_memalign(mstate, size_t, size_t);
static void* _mid_memalign(size_t, size_t, void *);
static void malloc_printerr(int action, const char *str, void *ptr, mstate av);
static void malloc_printerr(int action, const char *str, void *ptr, mstate av)
__attribute__ ((noreturn));
static void* internal_function mem2mem_check(void *p, size_t sz);
static int internal_function top_check(void);
@ -5408,24 +5409,8 @@ malloc_printerr (int action, const char *str, void *ptr, mstate ar_ptr)
if (ar_ptr)
set_arena_corrupt (ar_ptr);
if ((action & 5) == 5)
__libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message,
"%s\n", str);
else if (action & 1)
{
char buf[2 * sizeof (uintptr_t) + 1];
buf[sizeof (buf) - 1] = '\0';
char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);
while (cp > buf)
*--cp = '0';
__libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message,
"*** Error in `%s': %s: 0x%s ***\n",
__libc_argv[0] ? : "<unknown>", str, cp);
}
else if (action & 2)
abort ();
__libc_message (do_abort, "%s\n", str);
__builtin_unreachable ();
}
/* We need a wrapper function for one of the additions of POSIX. */

View File

@ -1309,17 +1309,15 @@ The block was already freed.
Another possibility to check for and guard against bugs in the use of
@code{malloc}, @code{realloc} and @code{free} is to set the environment
variable @code{MALLOC_CHECK_}. When @code{MALLOC_CHECK_} is set, a
special (less efficient) implementation is used which is designed to be
tolerant against simple errors, such as double calls of @code{free} with
the same argument, or overruns of a single byte (off-by-one bugs). Not
all such errors can be protected against, however, and memory leaks can
result. If @code{MALLOC_CHECK_} is set to @code{0}, any detected heap
corruption is silently ignored; if set to @code{1}, a diagnostic is
printed on @code{stderr}; if set to @code{2}, @code{abort} is called
immediately. This can be useful because otherwise a crash may happen
much later, and the true cause for the problem is then very hard to
track down.
variable @code{MALLOC_CHECK_}. When @code{MALLOC_CHECK_} is set to a
non-zero value, a special (less efficient) implementation is used which
is designed to be tolerant against simple errors, such as double calls
of @code{free} with the same argument, or overruns of a single byte
(off-by-one bugs). Not all such errors can be protected against,
however, and memory leaks can result.
Any detected heap corruption results in immediate termination of the
process.
There is one problem with @code{MALLOC_CHECK_}: in SUID or SGID binaries
it could possibly be exploited since diverging from the normal programs

View File

@ -71,27 +71,13 @@ following tunables in the @code{malloc} namespace:
This tunable supersedes the @env{MALLOC_CHECK_} environment variable and is
identical in features.
Setting this tunable enables a special (less efficient) memory allocator for
the malloc family of functions that is designed to be tolerant against simple
errors such as double calls of free with the same argument, or overruns of a
single byte (off-by-one bugs). Not all such errors can be protected against,
however, and memory leaks can result. The following list describes the values
that this tunable can take and the effect they have on malloc functionality:
@itemize @bullet
@item @code{0} Ignore all errors. The default allocator continues to be in
use, but all errors are silently ignored.
@item @code{1} Report errors. The alternate allocator is selected and heap
corruption, if detected, is reported as diagnostic messages to @code{stderr}
and the program continues execution.
@item @code{2} Abort on errors. The alternate allocator is selected and if
heap corruption is detected, the program is ended immediately by calling
@code{abort}.
@item @code{3} Fully enabled. The alternate allocator is selected and is fully
functional. That is, if heap corruption is detected, a verbose diagnostic
message is printed to @code{stderr} and the program is ended by calling
@code{abort}.
@end itemize
Setting this tunable to a non-zero value enables a special (less
efficient) memory allocator for the malloc family of functions that is
designed to be tolerant against simple errors such as double calls of
free with the same argument, or overruns of a single byte (off-by-one
bugs). Not all such errors can be protected against, however, and memory
leaks can result. Any detected heap corruption results in immediate
termination of the process.
Like @env{MALLOC_CHECK_}, @code{glibc.malloc.check} has a problem in that it
diverges from normal program behavior by writing to @code{stderr}, which could