Skip to content

Randomize the layout of zend_mm small freelists - #23361

Open
jvoisin wants to merge 1 commit into
php:masterfrom
jvoisin:randlist
Open

Randomize the layout of zend_mm small freelists#23361
jvoisin wants to merge 1 commit into
php:masterfrom
jvoisin:randlist

Conversation

@jvoisin

@jvoisin jvoisin commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

zend_mm_alloc_small_slow() carved a fresh bin into a freelist ordered by ascending address and returned the first element, so the address of every small allocation was entirely determined by the allocation sequence: the n-th allocation of a given size class always landed at bin + n*slot_size, and two consecutive allocations were always adjacent.

That determinism is what makes heap feng-shui reliable. An attacker who can drive a few allocations of the right size class knows exactly where the next one lands, and can therefore place a victim object immediately after a buffer he can overflow, or reclaim a specific freed slot with an object of a chosen type.

Shuffle the slot order when a bin is created: hand out the first slot of the shuffled sequence and link the remaining ones in that order. This is the ~equivalent of Linux' SLAB_FREELIST_RANDOM.

Performance-wise, it:

  • Adds two scratch arrays of ZEND_MM_MAX_BIN_ELEMENTS entries (4KiB total) live on the stack of a non-recursive slow path.
  • Adds a per-bin-creation shuffleing, on the slow path.
  • Reduces spatial locality of allocations, but Zend/bench.php shows no measurable difference.

Can be compiled out with -DZEND_MM_FREELIST_RANDOM=0.

zend_mm_alloc_small_slow() carved a fresh bin into a freelist ordered by
ascending address and returned the first element, so the address of every
small allocation was entirely determined by the allocation sequence: the
n-th allocation of a given size class always landed at bin + n*slot_size,
and two consecutive allocations were always adjacent.

That determinism is what makes heap feng-shui reliable. An attacker who
can drive a few allocations of the right size class knows exactly where
the next one lands, and can therefore place a victim object immediately
after a buffer he can overflow, or reclaim a specific freed slot with an
object of a chosen type.

Shuffle the slot order when a bin is created: hand out the first slot of
the shuffled sequence and link the remaining ones in that order. This is
the ~equivalent of Linux' SLAB_FREELIST_RANDOM.

Performance-wise, it:

- Adds two scratch arrays of ZEND_MM_MAX_BIN_ELEMENTS entries (4KiB total) live
  on the stack of a non-recursive slow path.
- Adds a per-bin-creation shuffleing, on the slow path.
- Reduces spatial locality of allocations, but Zend/bench.php shows no
  measurable difference.

Can be compiled out with -DZEND_MM_FREELIST_RANDOM=0.
@jvoisin

jvoisin commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Part of #14083

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant