← All rules
SOCLE-CLD-MOD-014// Kernel modulesmediumeffective runtime

Disable loading and unloading of kernel modules

Set kernel.modules_disabled=1 so the kernel refuses to load or unload any module for the rest of the uptime, even for root. Once set, the switch cannot be reverted without a reboot.

Checked against the resolved running state (e.g. sshd -T, sysctl, systemctl show), catches drop-ins and Includes a file read would miss. Caveat: runtime ≠ persistence; a value correct now may not survive a reboot.

A pass proves✓ running now✓ on disk✓ survives rebootthe qualified verdict →
Debian 12CIS 1.1.0Debian 13CIS 1.0.0FedoraRHEL 10 / Rocky 10 / AlmaLinux 10RHEL 8 / Rocky 8 / AlmaLinux 8CIS 4.0.0RHEL 9 / Rocky 9 / AlmaLinux 9CIS 2.0.0Ubuntu 22.04CIS 3.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04
One check, maps to 1 standard

Pavois asserts the effective configuration, the live, resolved state, not a file. File-based scanners (OVAL/SCAP, Lynis) miss Includes, drop-ins and runtime defaults; this check sees what is actually applied.

A mapping is a cross-reference to where each standard places this requirement, anchored and cross-validated, not a claim of equivalence. A passing check is evidence toward these references, how to read it.

Why this rule matters

Malicious kernel modules can have a significant impact on system security and availability. Disabling loading of kernel modules prevents this threat. Note that once this option has been set, it cannot be reverted without doing a system reboot. Make sure that all needed kernel modules are loaded before setting this option.

What Pavois checks

Pavois reads the effective value from /proc/sys/kernel/modules_disabled (the InSpec kernel_parameter resource), which is the switch the kernel actually honours at each module load. A second check proves persistence: it greps /etc/sysctl.conf, the sysctl.d directories and the systemd units under /etc/systemd/system/*.service, because Pavois applies this one through a late-running unit rather than a plain sysctl drop-in (see the remediation). A runtime value alone would vanish at the next boot; a config file alone would prove nothing about the running kernel.

describe kernel_parameter('kernel.modules_disabled') do
  its('value') { should cmp 1 }
end
describe command("grep -hsE 'kernel.modules_disabled[[:space:]]*=[[:space:]]*1' /etc/sysctl.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /lib/sysctl.d/*.conf /etc/systemd/system/*.service 2>/dev/null") do
  its('stdout') { should match(/\S/) }
end

How to verify it is applied

Check the live switch, then prove it actually bites:

sysctl kernel.modules_disabled
# kernel.modules_disabled = 1
modprobe dummy
# modprobe: ERROR: could not insert 'dummy': Operation not permitted
systemctl is-enabled pavois-modules-disabled.service
# enabled

The last command is what guarantees the lock is re-applied at every boot.

Inspect & investigate

A refused module load returns EPERM (Operation not permitted) to the caller, so it surfaces in the logs of whatever tried to load it (journalctl -u <service>, dmesg), not in a dedicated log. The attempts themselves are recorded by the Pavois audit ruleset (init_module, finit_module, delete_module, key modules) in /var/log/audit/audit.log: grep the raw file for key="modules" rather than relying on ausearch, which is known to return false "no matches".

Remediation

Pavois does not write this key into its sysctl.d drop-in. systemd-sysctl runs during sysinit, before local-fs.target mounts /boot/efi: locking module loading that early means the vfat module can never load, local-fs fails, and the host drops into emergency mode (an unrecoverable brick when root has no password, observed on an EFI VM). Instead, Pavois writes a oneshot unit pavois-modules-disabled.service, ordered After=local-fs.target network-online.target, whose ExecStart is sysctl -q -w kernel.modules_disabled=1, and enables it: every boot-time module is loaded first, then module loading is locked. The lock is re-applied on each boot, and the rule carries reboot_required.

The rule is classified dangerous: harden apply never applies it on its own. It requires an explicit acknowledgement (acknowledged: true on the rule in the plan, or --i-understand-danger).

Pavois applies this with its own harden engine, the plan below, not a shell script:

keykernel.modules_disabled
reboot_requiredtrue
resourcesysctl
value1
pavois harden plan local

where the target is local, a user@host SSH alias, or a container , Docs

Impact & precautions

This is a one-way switch, which is why Pavois never applies it automatically. From the moment it is set, no module can be loaded until the next reboot: any driver not already resident is out of reach. Concretely:

  • The firewall can be stranded. The nftables ruleset Pavois deploys uses ct state, which needs nf_conntrack. If that module is not loaded when the lock closes, the ruleset fails to load and the host ends up with no firewall at all, or with its SSH access cut. That trade-off is why Pavois documents a waiver on hosts where a working firewall outranks the lock.
  • Hardware and filesystems can go missing. Hot-plugging a disk, a USB device or a NIC, or mounting a filesystem whose module was never loaded (vfat, nfs, xfs, a dm-* target), simply fails.
  • Container runtimes and VPNs break as soon as they load a module on demand (overlay, br_netfilter, wireguard, tun).

Before acknowledging it: inventory lsmod, pre-load every module you will need (/etc/modules-load.d/), make sure the firewall is up with its modules resident, keep console access (not just SSH), and plan a reboot to confirm the host comes back with the lock re-applied.

Standards mapping

StandardReferenceTypeVersionConfidence
ANSSI BP-028R10direct2.0high

Each reference is a cross-reference anchored in the upstream benchmark and cross-validated against the SCAP Security Guide and ansible-lockdown, not a claim of equivalence. Direct = a prescriptive, line-level requirement; supporting = an abstract control family (NIST) the check provides evidence toward. How to read a mapping.

Sources & references