Linux Security Modules
Standard Linux permissions (rwx bits, capabilities) are discretionary — the file owner decides who can access files. LSM (Linux Security Modules) adds mandatory access control: a policy administrator defines rules that override even root. SELinux and AppArmor are the two major LSM implementations.
DAC vs MAC — Two Security Models
| DAC (Discretionary) | MAC (Mandatory) | |
|---|---|---|
| Who sets policy | File owner | System administrator / policy |
| Can root bypass? | Yes — root ignores DAC | No — MAC applies to root too |
| Examples | chmod, chown, file permissions | SELinux, AppArmor |
| Granularity | User/group/other, capabilities | Per-process, per-file, per-operation |
| Default behavior | Allow unless denied | Deny unless explicitly allowed |
How LSM Hooks Work
How does SELinux intercept operations without modifying every system call?
LSM defines ~200 hook points in the kernel — one for every security-sensitive operation. "Check before opening this file." "Check before sending this signal." "Check before creating this socket." Each hook calls LSM's security_* function. The active LSM (SELinux or AppArmor) implements these functions. If the LSM denies the operation, it returns -EACCES and the operation fails — even for root.
LSM hook example (simplified kernel code):
int vfs_open(const struct path *path, struct file *file)
{
/* ... normal VFS checks ... */
error = security_file_open(file); // LSM hook
if (error)
return error; // denied by SELinux/AppArmor
/* ... proceed with open ... */
}
# Active LSM:
cat /sys/kernel/security/lsm
# lockdown,yama,apparmor (Ubuntu default)
# selinux (RHEL/Fedora default)
# Multiple LSMs can stack:
# lockdown = prevents root from modifying running kernel
# yama = restricts ptrace (parent can only trace children)
# apparmor = MAC profiles per process
LSM Stacking
# Modern kernels support stacking multiple LSMs
# Order matters: each LSM is consulted, all must allow
# Typical Ubuntu stack:
# 1. lockdown - prevents kexec, /dev/mem access, etc.
# 2. yama - ptrace scope restriction
# 3. apparmor - per-profile file/network/cap rules
# Typical RHEL stack:
# 1. lockdown
# 2. yama
# 3. selinux
# View what's loaded:
cat /sys/kernel/security/lsm
# Check if SELinux is enforcing:
getenforce
# Enforcing / Permissive / Disabled
# Check AppArmor status:
aa-status
Lockdown LSM
What does the lockdown LSM protect against?
Lockdown prevents even root from tampering with the running kernel — loading unsigned modules, accessing physical memory via /dev/mem, or bypassing Secure Boot. It has two levels: "integrity" (prevent kernel modification) and "confidentiality" (also prevent kernel memory reads). Enabled automatically when Secure Boot is active.
# Check lockdown level:
cat /sys/kernel/security/lockdown
# [none] integrity confidentiality
# Lockdown prevents:
# - kexec_load() when set to integrity
# - /dev/mem and /dev/kmem access
# - Loading unsigned kernel modules
# - Hibernation (could bypass integrity checks)
# - PCI BAR access from userspace