Skip to main content

Overview

The Thread Cache (tcache) is a per-thread caching mechanism introduced in glibc 2.26 to improve malloc performance. Each thread maintains 64 singly-linked lists of freed chunks, called tcache bins, organized by size. Understanding how requested sizes map to tcache indices is crucial for heap exploitation.
tcache is checked first before any other bins, making it the fastest allocation path and a prime target for exploitation.

What is tcache?

1

Per-thread cache

Each thread has its own tcache, eliminating lock contention for small allocations.
2

64 bins

Bins are indexed 0-63, covering small allocation sizes.
3

7 chunks per bin

By default, each bin holds up to 7 freed chunks (configurable via tcache_count).
4

Singly-linked list

Chunks in tcache are linked via a forward pointer, unlike doubly-linked bins.
5

LIFO allocation

Last freed chunk is the first to be reallocated (Last-In-First-Out).
tcache has minimal security checks compared to other bins, making it a popular exploitation target.

Index Calculation Formula

The tcache index is calculated differently depending on whether you have a chunk size or a requested size:

From Chunk Size

On 64-bit systems:

From User Request Size

On 64-bit systems:
The key insight: chunk sizes are aligned to 0x10 bytes, so each tcache index represents a 0x10-byte size class.

Demonstration Program

Here’s an interactive calculator for tcache indices:
calc_tcache_idx.c

Running the Calculator

Size to Index Mapping

Here’s a reference table for common allocations on 64-bit systems:
Pattern: Each index covers a 0x10-byte range of chunk sizes. To find the index for a chunk size, use: (chunksize - 0x20) / 0x10

Step-by-Step Calculation Example

Let’s calculate the tcache index for malloc(0x88):
1

Convert request to chunk size

2

Calculate tcache index

3

Verify range

Quick calculation: For chunk size 0x90, use: (0x90 - 0x20) / 0x10 = 0x70 / 0x10 = 7

Exploitation Implications

tcache Poisoning

By controlling the forward pointer of a freed chunk in tcache, you can make malloc return an arbitrary address:
Modern glibc (2.32+) includes safe linking to mitigate this, but tcache poisoning remains effective on older versions.

tcache Dup (Double Free)

In glibc 2.29+, a simple double-free check was added, but it only checks if the head of the tcache list matches the chunk being freed.

Size Confusion

If you can corrupt a chunk’s size field, you can control which tcache bin it goes to:

Why tcache Index Matters

Understanding tcache indexing is critical for:

Heap Grooming

Precisely control which bins are filled to influence allocation behavior

Size Confusion

Exploit size field corruption to misplace chunks in bins

tcache Poisoning

Target specific bins for arbitrary allocation exploits

Bypass Mitigations

Understand which sizes avoid security checks

Practical Tips

Fill tcache before exploiting: Many exploits require filling tcache bins (7 chunks) so that subsequent frees go to other bins like fastbins or unsorted bins.
Avoid tcache with large sizes: Allocate > 0x400 bytes to bypass tcache entirely:
Use the calculator during CTFs: This program is invaluable during competitions for quickly determining which bin your allocations will use.

tcache vs Other Bins

tcache’s minimal security checks and per-thread nature make it the easiest target for exploitation on modern glibc.

tcache Poisoning

Full exploitation technique using tcache

House of Botcake

Modern tcache double-free bypass

Heap Basics

Overview of all bin types

First Fit

Allocation strategy fundamentals

Summary

Key Takeaways:
  • tcache uses 64 bins (indices 0-63) for chunks up to 0x410 bytes
  • Index formula: (chunksize - 0x20) / 0x10 on 64-bit
  • User request size must be converted to chunk size first
  • tcache has minimal security checks, making it exploitable
  • Understanding index calculation is essential for heap grooming