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.
| Permission | Meaning | Protection it provides |
|---|---|---|
| Present | Page is mapped and in memory | Unmapped addresses fault immediately |
| Read/write | Page may be written, or is read-only | Protects code and constants from modification |
| User/supervisor | Page is accessible from user mode or only the kernel | Shields kernel memory from applications |
| No-execute (NX) | Code may not run from this page | Blocks injected code in stacks and heaps |
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.
| Architecture | Kernel level | User level | Additional levels |
|---|---|---|---|
| x86-64 | Ring 0 | Ring 3 | Hypervisor mode, System Management Mode |
| Arm (AArch64) | EL1 | EL0 | EL2 hypervisor, EL3 secure monitor |
| RISC-V | Supervisor mode | User mode | Machine mode, hypervisor extension |
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 and related security features
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.
| Mechanism | What it does | Relationship to memory protection |
|---|---|---|
| Process isolation | Separates processes from each other | Direct result of separate address spaces |
| Executable space protection | Marks data regions non-executable | Uses the NX permission bit |
| ASLR | Randomizes memory layout | Makes protected regions hard to locate |
| Control-flow integrity | Restricts where code may jump | Covers attacks that reuse existing code |
| Memory tagging | Tags allocations to catch misuse | Adds finer granularity than pages |
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.
| Platform | Typical message | Usual cause |
|---|---|---|
| Windows | Access violation, exception code 0xC0000005 | Invalid pointer or write to read-only memory |
| Linux and macOS | Segmentation fault (SIGSEGV) | Access outside mapped or permitted pages |
| Kernel fault on Windows | Stop error with a bug check code | Driver touched invalid memory in kernel mode |
| Kernel fault on Linux | Kernel oops or panic | Kernel or driver memory error |
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.