I added a section to the hardened malloc documentation on the chosen approach to memory tagging for slab allocations:
github.com/AndroidHardeni
In addition to guaranteed linear overflow detection, it will guarantee that use-after-free is detected until the tag wraps all the way.
Conversation
Despite only having 4 bit tags, it's guaranteed to take fairly long to wrap around due to the FIFO quarantine providing a guaranteed delay on reuse of the slot each time. The randomized portion of the quarantine and randomized slot / slab selection will give it even more value.
1
1
The initial tag values will be randomly chosen via the same efficient ChaCha8 CSPRNG already used for several other purposes. Randomized tags provide a baseline of weak probabilistic heap corruption detection between any allocations, but deterministic guarantees are much nicer.
1
2
It will also be possible to use memory tagging for large allocations, but those are already guaranteed to have randomly sized guard regions (at least 1 guard page) on each side and there's a virtual memory quarantine guaranteeing that address space isn't used again for a while.
1
For large allocations it would be used solely as a probabilistic mitigation for accesses between allocations and to a lesser extent probabilistic use-after-free mitigation. They already get replaced with a PROT_NONE mapping via MAP_FIXED on free and that region is quarantined.
2
Replying to
1
1
Replying to
On Linux, MAP_STACK is a no-op and secondary stack mappings are just a contiguous, static mapping like other mmap mappings so it doesn't really matter. The main thread stack is a special case and has a properly enforced gap that's not a PROT_NONE region so it can't grow into one.
2
The enforced gap is a special reserved area rather than an actual normal mapping. Secondary stacks are just a mapping made by the libc pthread_create implementation (or the caller, if they provide their own stack) with a guard region. I improved that in my past libc hardening.
1
In my previous Bionic hardening, I added randomly sized guard regions on both ends similar to how I handle large allocations in the hardened allocator along with randomizing the stack pointer within the initial page to a certain extent up to a limit like 2% of available space.
1
Replying to
That's something I need to look into for HardenedBSD again: random-sized MAP_GUARD stack guard pages for per-thread stacks.
1
Replying to
You can see how it's implemented:
github.com/AndroidHardeni
It's only tricky for aligned allocations (not applicable to stacks) and isn't that complex.
Here's where it chooses the random guard size:
github.com/AndroidHardeni
It's stored alongside size:
github.com/AndroidHardeni
I meant to link to pages.c rather than memory.c:
github.com/AndroidHardeni
The whole purpose of pages.c / pages.h is to provide a wrapper around memory.c / memory.h implementing support for guard pages in a mostly transparent way. It's not entirely transparent due to realloc.
1
1
Since realloc actually has to be aware of how the guard pages work for the efficient approaches to large allocation shrinking, growth and moving pages to a new location with the mapping already reserved via MREMAP_MAYMOVE|MREMAP_FIXED. Those are just optimized fast paths though.
2
Show replies

