Memory protection

On this page 7

Memory protection is the combination of processor hardware and operating system rules that prevents a process from accessing memory it does not own or from using memory in a way it is not permitted to, such as writing to code or executing data. In OS security, memory protection is the foundation on which process isolation, privilege separation and most exploit mitigations are built.

Without it, a single faulty or malicious program could overwrite the kernel or read another application’s passwords. With it, such an attempt triggers a hardware fault, and the operating system terminates the offending process instead of letting the damage spread.

How memory protection works in hardware

Memory protection works through the memory management unit (MMU), which translates every virtual address a program uses into a physical address. Each process receives its own virtual address space, described by page tables that the kernel controls. A process can only reach physical memory that its page tables map, so memory belonging to other processes is simply invisible to it.

Each page table entry also carries permission bits. On every access, the MMU checks them in hardware, and a violation raises a page fault or protection fault that transfers control to the kernel. The translation results are cached in the translation lookaside buffer (TLB), which keeps these checks fast enough to run on every instruction.

PermissionMeaningProtection it provides
PresentPage is mapped and in memoryUnmapped addresses fault immediately
Read/writePage may be written, or is read-onlyProtects code and constants from modification
User/supervisorPage is accessible from user mode or only the kernelShields kernel memory from applications
No-execute (NX)Code may not run from this pageBlocks injected code in stacks and heaps
Key page-level permission bits

Pages are typically 4 KB in size on x86-64 and many Arm systems, with larger pages of 2 MB or 1 GB available for performance. Protection is therefore applied at page granularity, which is why smaller bugs inside a single page are not caught by the MMU alone.

The role of privilege levels

Memory protection depends on processor privilege levels, because only privileged code may change page tables. If an application could edit its own mappings, it could grant itself access to anything. The CPU therefore distinguishes kernel mode from user mode.

ArchitectureKernel levelUser levelAdditional levels
x86-64Ring 0Ring 3Hypervisor mode, System Management Mode
Arm (AArch64)EL1EL0EL2 hypervisor, EL3 secure monitor
RISC-VSupervisor modeUser modeMachine mode, hypervisor extension
Privilege levels on common architectures

Applications request kernel services through system calls, a controlled entry point that switches the privilege level and validates arguments. Kernel features such as SMEP and SMAP on x86, or PXN and PAN on Arm, add the reverse protection: they stop the kernel from accidentally executing or reading user-space memory, which closes a common exploitation route.

Memory protection is the base layer of defense, and several neighboring features in OS security either build on it or fill its gaps. They target different stages of an attack, so systems combine them rather than choosing one.

MechanismWhat it doesRelationship to memory protection
Process isolationSeparates processes from each otherDirect result of separate address spaces
Executable space protectionMarks data regions non-executableUses the NX permission bit
ASLRRandomizes memory layoutMakes protected regions hard to locate
Control-flow integrityRestricts where code may jumpCovers attacks that reuse existing code
Memory taggingTags allocations to catch misuseAdds finer granularity than pages
How memory protection relates to neighboring mechanisms

A common policy built on these bits is W^X, meaning a page may be writable or executable but never both. It forces just-in-time compilers in browsers and runtimes to switch permissions explicitly, which leaves a narrower window for attackers to inject code.

What memory protection does not prevent

Memory protection stops cross-boundary access, but it does not prevent bugs inside a process’s own memory. A buffer overflow that corrupts adjacent data in the same writable page is entirely legal from the MMU’s point of view.

  • In-process corruption: overflows and use-after-free bugs within one address space remain possible.
  • Code reuse attacks: return-oriented programming chains existing executable code and bypasses NX.
  • Kernel bugs: a flaw in privileged code can rewrite page tables and disable protection.
  • Side channels: speculative execution flaws such as Meltdown leaked kernel memory despite permission checks.
  • Direct memory access: devices can bypass the CPU’s MMU unless an IOMMU restricts them.

These gaps explain the layered design of modern systems. Kernel page-table isolation was introduced to address Meltdown, the IOMMU confines devices, and memory-safe languages reduce in-process corruption at the source.

Symptoms and practical consequences

When memory protection catches a violation, the visible result is usually a crash of the faulting program, not of the whole system. The messages differ by platform but share the same cause.

PlatformTypical messageUsual cause
WindowsAccess violation, exception code 0xC0000005Invalid pointer or write to read-only memory
Linux and macOSSegmentation fault (SIGSEGV)Access outside mapped or permitted pages
Kernel fault on WindowsStop error with a bug check codeDriver touched invalid memory in kernel mode
Kernel fault on LinuxKernel oops or panicKernel or driver memory error
How protection faults appear to users

A crash in kernel mode is more severe because there is no higher authority to contain it. This is why faulty drivers cause system-wide stop errors, and why platforms increasingly move drivers out of the kernel and require driver signing.

In plain words

Memory protection works like locked apartments in a building. Every program gets its own apartment, and the building’s security system checks every door it tries to open. If a program tries to walk into a neighbor’s apartment or the manager’s office, the alarm goes off and that program is removed.

Some rooms are also marked for specific uses: you may read the notices on the wall but not rewrite them. The key idea is that one misbehaving program should not be able to harm the others or the system itself.

A real-world example

A user opens a malicious document in an outdated PDF reader. The file triggers a buffer overflow that places attacker code on the program’s stack and redirects execution to it.

Because the stack is marked non-executable, the processor refuses to run the injected code and raises a fault; Windows terminates the reader with an access violation. Even if the attacker had used a code-reuse technique to succeed inside the reader, separate address spaces would keep the browser’s stored passwords out of reach, and user/supervisor bits would block direct access to the kernel. The outcome is a crashed application and a log entry instead of a compromised computer, and the security team patches the reader the same day.