This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix tcache count maximum
- From: Wilco Dijkstra <Wilco dot Dijkstra at arm dot com>
- To: "libc-alpha at sourceware dot org" <libc-alpha at sourceware dot org>
- Cc: nd <nd at arm dot com>, DJ Delorie <dj at redhat dot com>
- Date: Mon, 15 Apr 2019 14:32:59 +0000
- Subject: [PATCH] Fix tcache count maximum
There are 2 issues with tcache count: the tcache counts[] array
is a char, which may be signed and has a very small range and thus
may overflow. When setting it, there is no overflow check.
Eg. export GLIBC_TUNABLES=glibc.malloc.tcache_count=4096
leads to various crashes in benchtests:
Running /build/glibc/benchtests/bench-strcoll
bench-strcoll: malloc.c:2949: tcache_get: Assertion `tcache->counts[tc_idx] > 0' failed.
Aborted
Btw is this kind of crash regarded as a security risk? It's easy to do a
denial of service this way if you're able to set an environment variable.
ChangeLog:
2019-04-15 Wilco Dijkstra <wdijkstr@arm.com>
* malloc/malloc.c (tcache_perthread_struct): Use an
unsigned short for counts array.
(MAX_TCACHE_COUNT): New define.
(do_set_tcache_count): Only update if count is small enough.
--
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 801ba1f499b566e677b763fc84f8ba86f4f7ccd0..4db7283cc27118cd7d39410febf7be8f7633780a 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2915,10 +2915,12 @@ typedef struct tcache_entry
time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
- char counts[TCACHE_MAX_BINS];
+ unsigned short counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
+#define MAX_TCACHE_COUNT 65535 /* Maximum value of counts[] entries. */
+
static __thread bool tcache_shutting_down = false;
static __thread tcache_perthread_struct *tcache = NULL;
@@ -5114,8 +5116,11 @@ do_set_tcache_max (size_t value)
static __always_inline int
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;
}