[PATCH 0/1] Improved double free detection in the tcache.
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Fri Apr 25 16:17:06 GMT 2025
Hi David,
The new version looks good in terms of correctness. A few minor things:
- it needs rebasing to latest trunk (there were changes to tcache_double_free_verify)
- there are a few code formatting issues (see below)
- the commit message could be improved to describe the actual changes made
(it discusses alternatives but not that it now scans through all sizes)
- please include libc-alpha so that it gets posted to the mailing list and tested
- the attachment you used does not get recognized and thus none of the tests run,
so could you try just copying the patch into the email body?
+tcache_double_free_verify (tcache_entry *e)
+ for (size_t tc_idx = 0; tc_idx < TCACHE_MAX_BINS; ++tc_idx) {
The '{' should be on the next line indented by 2 more spaces, and the
body then by another 2. The 'for' seems to be indented by 4 rather than 2.
+ size_t cnt = 0;
+ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
+ for (tmp = tcache->entries[tc_idx];
+ tmp;
+ tmp = REVEAL_PTR (tmp->next), ++cnt)
+ {
+ if (cnt >= mp_.tcache_count)
+ malloc_printerr ("free(): too many chunks detected in tcache");
+ if (__glibc_unlikely (!aligned_OK (tmp)))
+ malloc_printerr ("free(): unaligned chunk detected in tcache 2");
+ if (tmp == e)
+ malloc_printerr ("free(): double free detected in tcache 2");
+ }
Odd indentation, have all tabs been removed?
+++ b/malloc/tst-tcfree4.c
@@ -0,0 +1,59 @@
+/* Test that malloc tcache catches double free.
+ Copyright (C) 2018-2025 Free Software Foundation, Inc.
Should be just 2025.
> - With "poison null byte" I meant using a terminating null byte and an
> off by one error
> to change the byte behind the buffer.
> - I added a testcase for this exact scenario (malloc/tst-tcfree4.c)
Thanks, that makes it clearer what case is being tested for.
> If there is a buffer overrun that overwrites more than the size field,
> the attacker would be able to overwrite the tcache_key and also the
> encrypted next pointer,
> thus making the check for the tcache_key useless.
Sure, if you somehow worked around the pointer swizzle, you could do
an overwrite that remains undetected.
> Yes, i think that in general sacrificing 8 byte of memory
> (or even better as you have suggested for 64 bit Systems truncating the
> tcache_key to 32 bytes
> and utilizing the 32 bit of the size field)
> to detect double frees would be a good tradeoff.
The main goal would not be to detect double frees (we need 1 bit for that),
but to reliably detect overwrites from the previous chunk. Storing more data
in the size field means we only need 1 load to get it all, which would make
the various checks simpler and cheaper.
> Also it would make leaking the tcahce_key harder.
> Because then the tchache_key would be before the pointer, that gets
> returned by malloc,
> thus a normal use after free would not leak the tcache_key.
True, however we don't consider it a secret - it could even be a constant value
in current usage. We should avoid using the word 'key' to avoid people thinking
it has to be cryptographically safe and protected from leaking...
> But I myself am totally new to the whole development of the glibc and
> therefor do not trust myself to
> implement this correctly.
Yes, I agree this would be complex since the current code is quite a mess.
Cheers,
Wilco
More information about the Libc-alpha
mailing list