skills/binary-exploitation/libc-heap/heap-memory-functions/free/SKILL.md
Analyze and explain glibc's free() function behavior for heap exploitation. Use this skill whenever the user asks about free(), heap chunk freeing, tcache/fastbin/unsorted bin behavior, double-free detection, safe-linking, tcache poisoning, or any glibc malloc/free internals. This skill explains the complete free() flow from __libc_free through _int_free to bin placement, including all security checks and error messages. Make sure to use this skill when debugging heap issues, analyzing heap exploitation primitives, or understanding why free() triggers specific error messages.
npx skillsauth add abelrguezr/hacktricks-skills glibc-free-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill explains the complete flow of free() in glibc's heap allocator, including security checks, bin placement logic, and exploitation considerations.
free(ptr)
└─> __libc_free
├─> NULL check → return
├─> mmaped chunk → munmap → return
└─> _int_free
├─> tcache (if eligible)
├─> fastbin (if eligible)
└─> _int_free_merge_chunk → unsorted bin
When free(ptr) is called:
| Check | Action |
|-------|--------|
| ptr == NULL | Return immediately (no-op) |
| Pointer tag mismatch | Double-free detection (if mtag_enabled) |
| chunk_is_mmapped(p) | Call munmap_chunk(p) and return |
| Otherwise | Add color, call _int_free(arena, p, 0) |
Key insight: free(NULL) is safe and does nothing.
Before any bin placement, _int_free performs critical checks:
| Check | Error Message |
|-------|---------------|
| Pointer not aligned | free(): invalid pointer |
| Size < MINSIZE or not aligned | free(): invalid size |
| Pointer wraps around address space | free(): invalid pointer |
These checks prevent many common heap corruption bugs from silently succeeding.
Eligibility: Chunk size fits in tcache bins AND tcache is enabled.
Checks before insertion:
| Check | Error Message |
|-------|---------------|
| tcache->counts[tc_idx] >= mp_.tcache_count | free(): too many chunks detected in tcache |
| Entry not aligned | free(): unaligned chunk detected in tcache 2 |
| Entry already in tcache (double-free) | free(): double free detected in tcache 2 |
Double-free detection: The code checks if e->key == tcache_key and walks the bin looking for the same pointer. This is probabilistic but effective.
glibc 2.42+ change: Tcache now accepts much larger chunks via glibc.malloc.tcache_max_bytes tunable. This means more frees go to tcache instead of unsorted bins.
Eligibility: size <= get_max_fast() AND (if TRIM_FASTBINS) chunk doesn't border top.
Checks before insertion:
| Check | Error Message |
|-------|---------------|
| Next chunk size invalid | free(): invalid next size (fast) |
| Chunk already at fastbin top | double free or corruption (fasttop) |
| Fastbin top has different size | invalid fastbin entry (free) |
Safe-linking: Fastbin fd pointers are protected: PROTECT_PTR(pos, ptr) = ((size_t)pos >> 12) ^ (size_t)ptr
If chunk doesn't fit tcache or fastbin, it goes through consolidation:
Checks during consolidation:
| Check | Error Message |
|-------|---------------|
| Chunk is top chunk | double free or corruption (top) |
| Next chunk outside arena | double free or corruption (out) |
| Next chunk not marked in-use | double free or corruption (!prev) |
| Next chunk size invalid | free(): invalid next size (normal) |
| Prev size mismatch during consolidation | corrupted size vs. prev_size while consolidating |
Process:
Tcache and fastbin use safe-linking to protect fd pointers:
# To craft a safe-linked fd pointing to TARGET:
# You need a leaked heap address at position POS
protected_fd = TARGET ^ (POS >> 12)
Implication: You need a heap leak to perform tcache poisoning. The XOR key is derived from the position of the fd pointer itself.
The detection works by:
e->key == tcache_key (probabilistic match)mp_.tcache_count entriesBypass consideration: The key check is probabilistic (1 in 2^size_t chance of false positive), but the pointer walk is deterministic.
For research/testing, use GLIBC_TUNABLES to control tcache:
# Disable tcache completely (see classic unsorted bin behavior)
GLIBC_TUNABLES=glibc.malloc.tcache_count=0 ./program
# glibc 2.42+: Disable large tcache
GLIBC_TUNABLES=glibc.malloc.tcache_max_bytes=0 ./program
__malloc_hook and __free_hook overwrites are not viable on glibc ≥ 2.34. Use alternative targets:
| Error | Cause |
|-------|-------|
| free(): invalid pointer | Misaligned or wrapped pointer |
| free(): invalid size | Size < MINSIZE or not aligned |
| free(): too many chunks detected in tcache | Tcache bin overflow |
| free(): unaligned chunk detected in tcache 2 | Tcache entry misalignment |
| free(): double free detected in tcache 2 | Same chunk freed twice (tcache) |
| free(): invalid next size (fast) | Next chunk size invalid (fastbin) |
| double free or corruption (fasttop) | Chunk already at fastbin top |
| invalid fastbin entry (free) | Fastbin size mismatch |
| double free or corruption (top) | Freeing top chunk |
| double free or corruption (out) | Next chunk outside arena |
| double free or corruption (!prev) | Next chunk not marked in-use |
| free(): invalid next size (normal) | Next chunk size invalid (normal) |
| corrupted size vs. prev_size while consolidating | Prev size field mismatch |
When analyzing a heap bug involving free():
fd pointers to control allocationtesting
How to perform a House of Lore (small bin attack) heap exploitation. Use this skill whenever the user mentions heap exploitation, small bin attacks, fake chunks, glibc heap vulnerabilities, or needs to insert fake chunks into small bins for arbitrary read/write. Trigger for CTF challenges involving heap corruption, glibc 2.31+ exploitation, or when the user needs to bypass malloc sanity checks using fake chunk linking.
testing
How to perform House of Force heap exploitation attacks. Use this skill whenever the user mentions heap exploitation, House of Force, top chunk manipulation, arbitrary memory allocation, malloc manipulation, or wants to allocate chunks at specific addresses. Also trigger for CTF challenges involving heap overflows, top chunk size overwrites, or when the user needs to calculate evil_size for heap attacks. Make sure to use this skill for any binary exploitation task involving glibc heap manipulation, even if they don't explicitly say "House of Force".
tools
How to perform House of Einherjar heap exploitation to allocate memory at arbitrary addresses. Use this skill whenever the user mentions heap exploitation, glibc heap attacks, arbitrary memory allocation, off-by-one overflow exploitation, tcache poisoning, fast bin attacks, or any CTF challenge involving heap manipulation. This is essential for binary exploitation tasks where you need to control malloc() return addresses.
testing
How to identify, analyze, and exploit heap overflow vulnerabilities in binary exploitation challenges and real-world scenarios. Use this skill whenever the user mentions heap overflows, memory corruption, heap grooming, tcache poisoning, fast-bin attacks, or any heap-related vulnerability in CTF challenges, binary analysis, or security research. This skill covers heap overflow fundamentals, exploitation techniques, heap grooming strategies, and real-world CVE analysis.