Course contentsShow
← Linux
Lesson 981 of 1,8199. Security Hardening and Mandatory Access ControlFree lesson

Handling Executable Memory Mapping

Restrict memory protection flags to prevent the execution of malicious code in data segments.

In this lesson, you will learn how to restrict memory protection flags to prevent the execution of malicious code injected into data segments.

The Threat of W^X (Write XOR Execute)

Modern security architectures rely on the W^X principle, which mandates that memory segments should either be writable or executable, but never both simultaneously. When an attacker manages to inject malicious shellcode into a process’s memory, they typically attempt to execute that code by mapping a memory region with both PROT_WRITE and PROT_EXEC flags. By enforcing strict memory mapping controls, we can block these attempts, forcing the system to deny any request that violates memory safety.

Controlling Mappings with AppArmor

While the kernel manages hardware-level memory protections via the Memory Management Unit (MMU), AppArmor provides an additional layer of policy enforcement to restrict how processes interact with their own memory maps.

If a process is compromised, an attacker might try to use mmap() or mprotect() to change a data buffer into an executable region. In your AppArmor profiles, you can restrict the ability of a process to manage its memory protections, preventing it from marking writable segments as executable.

While AppArmor is primarily path-based, you can use the deny rule combined with capability restrictions to limit the influence a process has over its own memory layout. For example:

# Prevent the application from making unauthorized memory modifications
deny capability sys_rawio,
deny /proc/[0-9]*/mem w,

Why This Matters

If an attacker exploits a buffer overflow, they must find a way to run their payload. By restricting the process's ability to manipulate its memory mappings, you ensure that the data segment—where user input is stored—remains strictly non-executable. Even if the attacker successfully overwrites a return address or injects code, the kernel and the security policy will refuse to execute that segment, effectively neutralizing the threat. This defense-in-depth approach ensures that memory corruption vulnerabilities are far harder to escalate into full system compromises.

Key Takeaway: By enforcing memory protection policies, you prevent the exploitation of memory-based vulnerabilities by ensuring that data segments remain non-executable, effectively blocking code injection attacks.