Skip to content

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:

Security Layers

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:

  1. Root bypasses everything: The superuser can bypass most DAC checks.
  2. Coarse granularity: Permissions are per-file, not per-application. Two applications running as the same user have identical access.
  3. Service compromise: A web server running as www-data can access all files that user owns, including secrets in config files unrelated to web serving.
  4. 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

  1. Hooks: The kernel calls the LSM at specific points (file open, network connect, process execution, etc.).
  2. Policy Lookup: Each LSM checks the request against its loaded policy.
  3. Decision: The LSM returns "Allowed" or "Denied".
  4. 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:

[^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