You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an opt-in, debug-only hardening mode for the free list, behind a compile-time knob,
that provides: (1) freed-block poisoning, (2) optional block canaries for
overflow/underflow detection, and (3) free-list next-pointer safe-linking (glibc-style
XOR obfuscation). Release builds stay byte-for-byte and cycle-for-cycle unchanged; the
hardening is a separate configuration.
An intrusive free list stores the next-pointer inside freed blocks, which is a classic
use-after-free / pointer-corruption exploitation primitive. The spec review (#105) flags
that the project has "no mention of pointer obfuscation, freed-block poisoning, or debug
canaries" despite the rest of the repo holding an enterprise/security posture
(SECURITY.md).
Motivation
Bug-finding. Poisoning turns silent use-after-free into a loud, deterministic crash
(reads of poisoned memory are obviously wrong; a poisoned next-pointer faults on the next alloc). Canaries catch the fixed-block internal-overflow case that ASan's redzones don't
see inside a pool-owned region.
Didactic value. Safe-linking is a real, shipping allocator hardening technique
(glibc ≥ 2.32). Demonstrating it — with an ADR explaining the threat model and the PROTECT_PTR/REVEAL_PTR transform — is squarely in this project's "exercise
production-grade techniques and justify them" mandate (ADR-0003).
Complements, not replaces, ASan: ASan is unavailable on MSVC and cannot instrument the
pool's own sub-block boundaries; a self-contained debug mode works everywhere the
library builds.
Design sketch (needs a new ADR — this touches the free-list layout, ADR-0009)
Compile-time knob, e.g. PBR_MEMORY_POOL_HARDENING (OFF by default), not a runtime
branch on the hot path — preserves the ADR-0014 benchmark numbers and the ADR-0015
overhead budget in release.
Poisoning: on free, fill the block with a recognizable pattern (e.g. 0xDEADBEEF) after threading the next-pointer; on alloc, optionally verify the pattern is intact
(detects writes to freed blocks) before handing the block out.
Safe-linking: store next XOR (addr >> PAGE_SHIFT) instead of the raw next-pointer,
so a leaked/overwritten free-list pointer is not directly usable and corruption is
detected via an alignment check on reveal. Access stays strict-aliasing-safe (ADR-0009).
Canaries: optional guard word(s) at block boundaries, validated on free; requires a
documented interaction with the block-size/alignment math (canaries cost usable bytes, so
this is a distinct sub-mode, possibly its own knob).
Must work across dynamic-growth chunks (ADR-0022/0023) and remain compatible with the
thread-safe configuration (ADR-0020) and the InstrumentedPool decorator (ADR-0025).
On detection: behaviour per a documented policy (abort with a diagnostic in debug),
reusing the foreign/double-free stance already set in ADR-0012 — and note
that safe-linking makes double-free detection cheaper.
Scope & compatibility
Additive & opt-in. Zero change to the frozen v1.0.0 ABI or to the default build.
SemVer MINOR (next MINOR, e.g. v1.2.0) per ADR-0004.
Because it changes the on-disk free-list encoding only when enabled, a hardened build is
not memory-layout-compatible with a non-hardened one — that is fine (never mix
configurations) and must be stated explicitly.
Acceptance criteria
New ADR records the threat model, the three sub-features, the on/off knob(s), and the
detection/abort policy; cross-links ADR-0009/0012/0015.
With hardening ON, a use-after-free, a buffer overflow past block_size, and a
double-free are each detected deterministically (covered by tests).
With hardening OFF, the benchmark (ADR-0014) and the metadata-overhead budget
(ADR-0015) are unchanged — verified.
Works with fixed and dynamic pools, single-thread and thread-safe configs.
README security section, SECURITY.md, spec §4, and Doxygen updated; patterns
catalogue updated if a pattern is introduced.
Clean under the full quality bar in both configurations.
Summary
Add an opt-in, debug-only hardening mode for the free list, behind a compile-time knob,
that provides: (1) freed-block poisoning, (2) optional block canaries for
overflow/underflow detection, and (3) free-list next-pointer safe-linking (glibc-style
XOR obfuscation). Release builds stay byte-for-byte and cycle-for-cycle unchanged; the
hardening is a separate configuration.
An intrusive free list stores the next-pointer inside freed blocks, which is a classic
use-after-free / pointer-corruption exploitation primitive. The spec review (#105) flags
that the project has "no mention of pointer obfuscation, freed-block poisoning, or debug
canaries" despite the rest of the repo holding an enterprise/security posture
(
SECURITY.md).Motivation
(reads of poisoned memory are obviously wrong; a poisoned next-pointer faults on the next
alloc). Canaries catch the fixed-block internal-overflow case that ASan's redzones don'tsee inside a pool-owned region.
(glibc ≥ 2.32). Demonstrating it — with an ADR explaining the threat model and the
PROTECT_PTR/REVEAL_PTRtransform — is squarely in this project's "exerciseproduction-grade techniques and justify them" mandate (ADR-0003).
pool's own sub-block boundaries; a self-contained debug mode works everywhere the
library builds.
Design sketch (needs a new ADR — this touches the free-list layout, ADR-0009)
PBR_MEMORY_POOL_HARDENING(OFF by default), not a runtimebranch on the hot path — preserves the ADR-0014 benchmark numbers and the ADR-0015
overhead budget in release.
free, fill the block with a recognizable pattern (e.g.0xDEADBEEF)after threading the next-pointer; on
alloc, optionally verify the pattern is intact(detects writes to freed blocks) before handing the block out.
next XOR (addr >> PAGE_SHIFT)instead of the raw next-pointer,so a leaked/overwritten free-list pointer is not directly usable and corruption is
detected via an alignment check on reveal. Access stays strict-aliasing-safe (ADR-0009).
free; requires adocumented interaction with the block-size/alignment math (canaries cost usable bytes, so
this is a distinct sub-mode, possibly its own knob).
thread-safe configuration (ADR-0020) and the
InstrumentedPooldecorator (ADR-0025).reusing the foreign/double-free stance already set in
ADR-0012 — and note
that safe-linking makes double-free detection cheaper.
Scope & compatibility
SemVer MINOR (next MINOR, e.g.
v1.2.0) per ADR-0004.not memory-layout-compatible with a non-hardened one — that is fine (never mix
configurations) and must be stated explicitly.
Acceptance criteria
detection/abort policy; cross-links ADR-0009/0012/0015.
block_size, and adouble-free are each detected deterministically (covered by tests).
(ADR-0015) are unchanged — verified.
SECURITY.md, spec §4, and Doxygen updated; patternscatalogue updated if a pattern is introduced.
References
canaries, and free-list next-pointer obfuscation")
SECURITY.md