public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] malloc tcache: Debugger now sees the address of the corrupted chunk.
@ 2020-12-07  0:57 Adder
  2020-12-11 22:51 ` DJ Delorie
  2020-12-12  3:17 ` DJ Delorie
  0 siblings, 2 replies; 13+ messages in thread
From: Adder @ 2020-12-07  0:57 UTC (permalink / raw)
  To: libc-alpha, dj, fweimer

If the user overwrites the "next" field of the tcache_entry
(i.e. the first 4 or 8 bytes at the address returned by malloc)
illegally (after having freed the chunk),
it is possible (and actually probable, especially on 64-bit platforms)
that the resulting pointer cannot be dereferenced.

Thus, a crash is caused upon a later allocation of similar size
(in our tcache_get function).

But at that point, only the "next" field is available to the debugger
(it has been copied in tcache->entries[tc_idx] and is being dereferenced).
In particular, the address of the corrupted chunk is not available.

To make it available and therefore to ease debugging,
we attempt to dereference (currently for reading) the "next" field earlier,
while the address of the chunk is still available.
---
 malloc/malloc.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/malloc/malloc.c b/malloc/malloc.c
index 5b87bdb0..6e1cae1c 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2946,6 +2946,45 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
   ++(tcache->counts[tc_idx]);
 }

+/* Upon free, we overwrite the beginning of the memory block with a
tcache_entry.
+   If the application (illegally) then overwrites the "next" field of
our tcache_entry,
+   a later tcache_get might cause a page fault (SIGSEGV)
+   when that field is (revealed and) dereferenced.
+
+   But at that point we are not going to see (in the debugger)
+   the address of the corrupted chunk -- only the (revealed) "next" field.
+
+   Let us dereference the "next" field while we still have the chunk address.
+   This consumes a few CPU cycles, but the extra information may help
debugging.
+
+   The "dbg_" parameters might seem redundant, but they are useful
for the debugger
+   (who might not otherwise be able to obtain their "optimized out" values).
+
+   This function is not inlined and not static in order to prevent
optimizations
+   and ensure all parameters are available.
+*/
+
+__attribute__ ((noinline)) tcache_entry *
+__libc_malloc_tcache_dbg_peek (const tcache_perthread_struct
*dbg_tcache, size_t dbg_tc_idx,
+                               const tcache_entry *dbg_e, const
tcache_entry *e_next)
+{
+  /* The caller does not use the result.
+     Therefore, the REVEAL_PTR computation is only for clarity.
+     But it might be useful later if we decide to walk for more than one step,
+     for earlier detection of the write-after-free bug.
+     (We do return a result in order to help prevent unwanted
optimizations.) */
+  return e_next ? REVEAL_PTR (e_next->next) : NULL;
+}
+
+static __always_inline tcache_entry *
+tcache_dbg_get_next (const tcache_perthread_struct *dbg_tcache,
size_t dbg_tc_idx,
+                     const tcache_entry *e)
+{
+  tcache_entry *const e_next = REVEAL_PTR (e->next);
+  __libc_malloc_tcache_dbg_peek (dbg_tcache, dbg_tc_idx, e, e_next);
+  return e_next;
+}
+
 /* Caller must ensure that we know tc_idx is valid and there's
    available chunks to remove.  */
 static __always_inline void *
@@ -2954,7 +2993,7 @@ tcache_get (size_t tc_idx)
   tcache_entry *e = tcache->entries[tc_idx];
   if (__glibc_unlikely (!aligned_OK (e)))
     malloc_printerr ("malloc(): unaligned tcache chunk detected");
-  tcache->entries[tc_idx] = REVEAL_PTR (e->next);
+  tcache->entries[tc_idx] = tcache_dbg_get_next (tcache, tc_idx, e);
   --(tcache->counts[tc_idx]);
   e->key = NULL;
   return (void *) e;
-- 
2.8.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-12-22  2:15 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-07  0:57 [PATCH] malloc tcache: Debugger now sees the address of the corrupted chunk Adder
2020-12-11 22:51 ` DJ Delorie
2020-12-11 23:48   ` Adder
2020-12-12  0:09     ` DJ Delorie
2020-12-12  3:17 ` DJ Delorie
2020-12-12  5:18   ` Adder
2020-12-12  5:32     ` DJ Delorie
2020-12-13  2:16       ` Adder
2020-12-16 22:30         ` DJ Delorie
2020-12-17  2:08           ` Adder
2020-12-17  4:18             ` DJ Delorie
2020-12-22  2:15               ` Adder
2020-12-17  9:34           ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).