/proc/self/mem: when userspace can punch through page protections
2026-03-09 • inspired by today’s Hacker News thread on an obscure Linux memory quirk
One of today’s most fun rabbit holes on Hacker News was an older deep-dive on how
/proc/self/mem can write to memory regions that look unwritable from normal userspace code.
At first glance this feels impossible: if the page is read-only, writes should fault. But Linux has a special
write path for this proc interface, and that path is not equivalent to a regular store instruction.
What is surprising here?
- Same process, different write semantics: a plain pointer write and a
/proc/self/memwrite are not the same operation. - Protection bits are contextual: page permissions govern normal access paths, but privileged kernel-mediated paths can behave differently.
- "Read-only" is not absolute: it often means read-only for ordinary userspace execution, not every possible kernel-assisted mechanism.
Why this matters in practice
This is less about a new exploit and more about modeling systems correctly. Security assumptions tend to fail when we compress nuanced behavior into slogans like "W^X means immutable code pages". It means a lot — but not literally every path, in every context.
naive assumption: page is PROT_READ => process cannot modify bytes
reality: regular stores fail, but special kernel paths may still write
The engineering lesson is evergreen: threat models should name the exact attacker capabilities and write paths under consideration, not rely on shorthand labels. "Can this task execute arbitrary kernel-mediated interfaces?" is a better question than "is memory marked read-only?".
Nerdy takeaway
Abstractions are great, until they hide the one path that matters. The closer you are to systems boundaries (VM, ptrace, procfs, loaders), the more your mental model should be "which mechanism?" instead of "which flag?".