Where Do LSMs Fit? A Linux Security Primer
Before diving into AppArmor or SELinux, it's worth understanding why Linux Security Modules exist and where they fit in the broader cybersecurity landscape.
The Cybersecurity Panorama: Defense in Depth
Modern security is not a single wall. It's a series of layers. If an attack manages to bypass a layer, the others should limit the damage.
Each layer addresses specific threats but has blind spots that the next layer must cover.
The main security layers can be seen in the following image:
Network Layer
The problem it solves: Malicious traffic should never reach your systems in the first place.
This layer includes:
- Firewalls: Filter traffic by IP, port, and protocol (e.g., iptables, nftables, cloud security groups).
- Web Application Firewalls (WAF): Inspect HTTP traffic for attacks like SQL injection and XSS.
- Intrusion Detection/Prevention (IDS/IPS): Detect and block known attack patterns.
What it doesn't solve: Once traffic is allowed through (e.g., a legitimate HTTPS request containing a malicious payload), the network layer cannot help. Encrypted traffic (TLS) is opaque to most network filters.
Application Layer
The problem it solves: Vulnerabilities in application code are the most common entry point for attackers.
This layer includes:
- Secure Development: Input validation, defensive programming, etc reduce the risk of vulnerabilities.
- Vulnerability Management: Patching, dependency scanning, SAST/DAST, etc.
- Unsafe Features & GTFOBins: Even legitimate binaries can be abused. See GTFOBins for examples
What it doesn't solve: New vulnerabilities are discovered every day. Logic flaws may not be caught by scanners. No application is bug-free. Some application can also be actively malicious.
Host/OS Layer
The problem it solves: The OS is responsible for the security of the system. It provides many mechanisms to enforce security policies, and is responsible for checking which entity can do which operation to every resource (files, sockets, IPC, etc.).
This layer includes:
- File Permissions (DAC)
- Capabilities: Reducing root privileges
- Seccomp: Restricting syscalls
- LSMs (AppArmor, SELinux): Mandatory Access Control
What it doesn't solve: If the policy is misconfigured or too permissive, protection is weakened. LSMs cannot prevent application to attempt to exploit vulnerabilities, but can limit their impact.
The Kernel Security Toolkit
Every operation an application does on a resource (opening a file, sending a network packet, spawning another process) goes through the kernel via system calls[^1]. Within these syscalls, many security mechanisms detailed below are responsible for checking if the operation is allowed or not
Seccomp/Seccomp-BPF
The problem it solves: The kernel now has more than 450 syscalls. Most applications use only a small fraction of them. Every unused syscall is a potential attack surface.
Seccomp can restrict which syscalls a process can make, and in some cases with which arguments. It is for instance possible to block sys_ptrace to prevent debugging attacks or sys_mount to prevent filesystem manipulation.
What it doesn't solve: Seccomp/Seccomp-BPF can filter syscalls, and their arguments but for security reasons it cannot dereference kernel pointers. Therefore it is not possible to allow/block on specific object.
For instance on long sys_open(const char __user *filename, int flags, umode_t mode);, seccomp can block based on the flags or the mode but NOT on the filename, which is a pointer.
Additionally, per-syscall filtering is brittle as many syscalls can be used for the same purpose. For instance, creat, open, openat, openat2 and new syscalls are regularly added to the kernel.
Linux Security Modules (presented below) don't have these limitations and are therefore the recommended way to implement fine-grained access control.
Access Control Models
The kernel controls access to resources. This is done with subsystems implementing Access Control Models (ACMs). ACMs are mathematical models describing how access to resources is determined.
These models are not mutually exclusive (e.g. DAC and MAC are very orthogonal) and are often combined to provide defense in depth. DAC is "built-in" to the kernel, while other ACMs are implemented by Linux Security Modules (LSMs).
The main ACMs supported by the Linux kernel are:
Discretionary Access Control (DAC)
The problem it solves: Multi-user systems need isolation (e.g. user A shouldn't read user B's files). DAC answers: "Does the user have permission?"
This is the traditional Unix permissions model:
- Every file has a field that notably tells if the {
user,group,others} can {read,write,execute} it. - The owner of a file and root can change these permissions at any time.
What it doesn't solve:
- Root bypasses everything: The superuser can bypass most DAC checks.
- Coarse granularity: Permissions are per-file, not per-application. Two applications running as the same user have identical access.
- Service compromise: A web server running as
www-datacan access all files that user owns, including secrets in config files unrelated to web serving. - Other issues: DAC doesn't protect against confused deputy attacks, is vulnerable to TOCTOU races, and cannot revoke access for already-open files.
DAC is not just for regular files
As "on Linux everything[^2] is a file", DAC can be used to control access to all kinds of resources, including sockets, IPC, mounts etc and not just regular files.
Mandatory Access Control (MAC)
The problem it solves: MAC enforces system-wide policies set by the administrator. This is orthogonal to DAC where the owner of resource sets up permision for these urces.
MAC policies confine subjects (e.g. applications), not just users. These policies are set by the administrator and cannot be overridden by users (and generally even by root).
This means that even if a subject gets compromised or abused, it cannot loosen its own confinement.
What it doesn't solve: MAC policies must be written and maintained. Overly permissive policies provide little protection. Overly restrictive policies break applications.
Linux Security Modules (LSMs) are the kernel framework that implements MAC.
Other Access Control Models
Some LSMs may be used to implement other ACMs.
- Role-Based Access Control (RBAC): Permissions are assigned to roles (e.g., "Auditor", "Admin"), and users/processes are assigned to roles. This simplifies management compared to assigning permissions to each individual user.
- Multi-Level Security (MLS): Classifies data and users by sensitivity levels (e.g., "Top Secret", "Unclassified"). A user cannot read data above their level ("No Read Up") or write data to a lower level ("No Write Down"), preventing data leaks.
- Attribute-Based Access Control (ABAC): Instead of roles, policies are purely based on attributes (time of day, location, compliance status).
- Mandatory Integrity Control (MIC): Focuses on data integrity (preventing unauthorized modification) rather than confidentiality (preventing unauthorized reading).
- ...
These extra models are not always needed but can be useful for specific use cases (e.g., MLS is often a legal requirement in military environments):
Linux Security Modules (LSM)
The Linux Security Module framework is kernel infrastructure that allows pluggable security policies. It provides hooks , an unified API to react on specific behaviors. For instance if a file was opened, the LSM hook file_open will be called, regardless of the syscall used to open the file. Additionally, LSM hooks have full visibility on the kernel struct and can dereference pointers to access any information related to the operation. It is thus possible to implement very fine-grained policies (e.g. based on the full path of a file).
LSM Hooks can register to the hooks they are interested in, to enforce their policy.
Why LSMs?
This article focuses on the "how". The why Linux relies on LSMs is discussed here and here.
How LSMs Work
- Hooks: The kernel calls the LSM at specific points (file open, network connect, process execution, etc.).
- Policy Lookup: Each LSM checks the request against its loaded policy.
- Decision: The LSM returns "Allowed" or "Denied".
- Enforcement: The operation is allowed only if all LSMs allow it.
Major vs Minor LSMs
Linux distinguishes between major and minor LSMs:
- Major LSMs implement a full MAC policy. They are mutually exclusive [^3].
- Minor LSMs implement focused security features. They can be stacked on top of each other.
A typical production system runs one major LSM and multiple minor LSMs
Major LSMs include: AppArmor, SELinux, Smack, TOMOYO, each providing a different approach to MAC with advantages and disadvantages.
The most commonly used major LSMs are AppArmor and SELinux, which provides different approach to MAC. A detailed comparison of AppArmor and SELinux is available in AppArmor vs SELinux.
Minor LSMs include:
| LSM | Purpose | How it works |
|---|---|---|
| Landlock | Unprivileged Sandboxing | Allows unprivileged processes to create their own sandbox (e.g., web browsers). |
| BPF LSM | Programmable Policy | Allows writing custom MAC policies using eBPF programs. |
| Capability | POSIX Capabilities | Implements the standard CAP_* checks (technically an LSM since Linux 2.6). |
| Yama | Ptrace Scope | Restricts ptrace usage (debugging) to prevent credential theft. |
| LoadPin | Boot Integrity | Ensures all kernel modules/firmware are loaded from a trusted filesystem. |
| Lockdown | Kernel Integrity | Prevents root from modifying the running kernel code (even if they want to). |
Audit & Observability
LSMs don't just block: they log. Every denial can be recorded, which is useful for:
- Policy Development and debugging: Understand what your application actually needs.
- Incident Response: Forensic analysis of what a compromised process attempted.
Conclusion
Linux Security Modules are a critical pillar of modern Linux security.
As the default major LSM in many distributions, AppArmor plays a significant role in Linux security.
Further reading:
- Write your first AppArmor profile manually or with aa-genprof
- Improve an existing profile with aa-notify aa-notify.
- See the reference manual of apparmor_parser
- Compare AppArmor and SELinux
[^1]: with rare exceptions for direct hardware access or shared memory operations where the kernel is bypassed for performance [^2]: with rare exceptions like signals and abstract sockets [^3]: some work has been done towards allowing stacking multiple major LSMs, but as some limitations still exist, it is not widely used on general purpose systems