Understanding AppArmor's position in the Linux kernel as a Linux Security Module, how it works alongside other modules like Yama and Landlock within a single LSM stack, CONFIG_SECURITY_APPARMOR configuration, runtime validation, and the division of roles between seccomp, capabilities, and LSMs at different layers.

In episode 15 you built oversight over confinement — denial logs, alerting, and baselines. Now it's time to zoom out: from configuration and tooling, we rise to the place where all those decisions are actually executed — the Linux kernel. The key question: what really happens inside the kernel when a process tries to open a profile-protected file?
This episode dissects AppArmor's position as a Linux Security Module, how it shares roles with other modules like Yama and Landlock in a single LSM stack, the kernel configuration that powers it, and the layer division between seccomp, capabilities, and LSMs.
The Linux Security Module (LSM) is a framework inside the kernel that provides hook points — hooks — on sensitive operations: opening a file, creating a socket, executing a binary, sending a signal, and many more. Every security module that wants to mediate those operations registers itself on these hooks.
Before kernel 4.4, only one "major" LSM could be active — you had to choose between AppArmor, SELinux, or Smack. Since kernel 4.4, the LSM framework supports stacking: several LSMs can be active at once, each mediating operations at the same hooks, in sequence. This is where AppArmor lives alongside other modules.
Think of it like airport checkpoints: several gates in a row, and every passenger passes through all of them in sequence. A passenger who clears the first gate hasn't cleared the rest — each module checks a different dimension.
On modern systems, the order of active LSMs is visible from the lsm= boot parameter. For distributions like Ubuntu, the default order is roughly: landlock, lockdown, yama, loadpin, safesetid, integrity, apparmor, selinux, smack, tomoyo. Within this list, AppArmor is a major LSM — the module that mediates access comprehensively. The other modules around it are minor LSMs with narrow focuses.
Three that most often interact with your day-to-day work:
ptrace between processes via the kernel.yama.ptrace_scope sysctl. It works in the same dimension as AppArmor's ptrace rules: both can restrict debugging and process injection. If both Yama and AppArmor are active, a process must pass both.An important point for you: when an AppArmor denial doesn't appear, don't immediately blame the profile. Other modules in the stack — or a combination of several — could be the decider. Diagnose by looking at denials across all layers, not just one.
The difference in dimensions between modules becomes visible during debugging. Say a process suddenly can't ptrace another process, even though its AppArmor profile already allows ptrace (trace). Possible causes: a wrong AppArmor ptrace rule, or Yama refusing because kernel.yama.ptrace_scope is set strictly. Two mechanisms, one symptom — and the solutions differ:
sysctl kernel.yama.ptrace_scope
sudo grep -n ptrace /etc/apparmor.d/usr.sbin.myappsysctl kernel.yama.ptrace_scope shows Yama's policy: 0 is free, 1 only direct children, 2 and 3 increasingly strict. Meanwhile grep -n ptrace shows the ptrace rule actually written in the profile. If Yama is refusing, the fix is in the sysctl; if AppArmor, the fix is in the profile. Looking at both sources before changing anything is a habit that saves you from changing the wrong configuration.
Tip
Rule of thumb: if a denial that appears doesn't show an AppArmor label in the logs, the cause is probably not AppArmor. SELinux writes AVC, seccomp writes SECCOMP_RET_, and Yama/Landlock don't always log anything. Read denials with eyes on all four layers.
For AppArmor to work, the kernel must be built with LSM support and AppArmor enabled:
CONFIG_SECURITY=y
CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_YAMA=y
CONFIG_SECURITY_LANDLOCK=y
CONFIG_SECURITYFS=y
CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo"The CONFIG_LSM line determines the order of modules tried at boot, and this configuration differs between distros — Debian, Ubuntu, and SUSE choose different combinations. To check the running kernel:
zcat /proc/config.gz | grep -E 'CONFIG_SECURITY|CONFIG_DEFAULT_SECURITY'If /proc/config.gz isn't available (usually because the configs module isn't loaded), check the config file in /boot/. Vanilla kernels from kernel.org usually don't enable AppArmor; distro-packaged kernels — Ubuntu, Debian, openSUSE — almost always build it with CONFIG_SECURITY_APPARMOR=y.
Kernel configuration is only a precondition; what matters is what's actually active at boot. There are several ways to validate it, and the fastest reads files the kernel itself builds:
cat /sys/kernel/security/lsm
cat /sys/module/apparmor/parameters/enabled
aa-status/sys/kernel/security/lsm lists the LSMs actually active, in their execution order. AppArmor must be on this list./sys/module/apparmor/parameters/enabled shows whether the AppArmor module is enabled via the apparmor=0 or apparmor=1 boot parameter.aa-status gives functional confirmation: loaded profiles and confined processes.Other boot parameters worth knowing: apparmor_restrict_unprivileged_userns=1 restricts the creation of unprivileged user namespaces — the restriction already discussed in episode 14 as a mitigation. Changes to the LSM order can also be made via the lsm=... boot parameter, but make them very carefully: order determines the stacking outcome.
One question that often confuses people: what's the difference between AppArmor and seccomp and capabilities, and aren't they all "restricting processes"? The answer is layers. All three mechanisms work at different points in a syscall's journey:
| Layer | What it checks | Example mechanism |
|---|---|---|
| seccomp | which syscalls may be called | Docker seccomp profile |
| LSM (AppArmor) | paths, network, capabilities, inter-process | AppArmor profile |
| Capabilities | privileges within a syscall | capability net_raw |
| DAC | file permissions based on owner and group | permission bits |
The usual check order: seccomp filters at the syscall entry point, then the LSM checks operations contextually (which path is touched, which socket is opened, against whom), while capabilities and DAC check privileges and permissions when the specific operation executes. A syscall must pass through all of them.
That difference is what makes the three complementary, not interchangeable. Seccomp is razor-sharp at the syscall level — it can block mount for all processes — but it doesn't know paths: two processes calling open are treated the same. AppArmor, by contrast, is context-based: the same profile can allow open on one path and deny it on another. That's the power you've been using throughout this series.
Tip
In the container world, all three are often installed together: an AppArmor profile for path-based policy, seccomp to trim unneeded syscalls, and minimized capabilities for minimal privilege. This is called defense in depth — and every layer checks a different dimension, so one layer's failure doesn't automatically mean total failure.
In this episode you've understood AppArmor in a broader context: it's an LSM within the kernel security framework, coexisting with Yama, Landlock, LoadPin, and others in a single stack; powered by CONFIG_SECURITY_APPARMOR and the CONFIG_LSM order; and validated via /sys/kernel/security/lsm and aa-status. You also saw the layer division with seccomp, capabilities, and DAC — all checking different dimensions in a syscall's journey.
The core takeaways:
CONFIG_SECURITY_APPARMOR=y; distro kernels generally are./sys/kernel/security/lsm and run aa-status.In episode 17 we dive into the advanced features that open new profile dimensions: mount rules, ptrace and signals, pivot_root, finer network filtering, transitions between profiles with child profiles and attach, and how policy versioning works between 4.x and 5.x formats. See you in episode 17!