kmod-guard - bloquer les modules noyau inutilisés
Installer et utiliser kmod-guard, un outil open source de webO3 qui bloque le chargement à la demande des modules noyau Linux qu'un serveur n'utilise pas.
kmod-guard - bloquer les modules noyau inutilisés
Installer et utiliser kmod-guard, un outil open source de webO3 qui bloque le chargement à la demande des modules noyau Linux qu'un serveur n'utilise pas.
Introduction
Plusieurs failles d'élévation de privilèges du noyau Linux se trouvent dans des modules qu'un utilisateur sans privilèges peut faire charger à la demande : une famille de sockets peu courante (sctp, tipc, vsock), une action de contrôle du trafic, une expression netfilter depuis un espace de noms utilisateur, un système de fichiers via mount(2), un algorithme AF_ALG. En 2026, Copy Fail, Dirty Frag, VsockDrop, OVSwrap, PPPoEject, RtabRace, DiagSpill, DirtyAH6, TUNderflow et plusieurs autres ont suivi ce schéma.
La mitigation habituelle consiste à ajouter une ligne install <module> /bin/false par CVE, après coup. kmod-guard le fait pour tous les modules d'un coup : tout ce qui n'est ni utilisé ni autorisé reçoit une ligne install dans /etc/modprobe.d/kmod-guard.conf.
- Aucun redémarrage, rien n'est déchargé. Supprimer le fichier annule tout instantanément.
- Un module chargé n'est jamais bloqué.
- Les pilotes matériels restent chargeables (par défaut).
Pour le contexte et les raisons derrière l'outil : Pourquoi on a créé kmod-guard.
Prérequis
- Linux avec systemd (le minuteur est optionnel)
- coreutils, diffutils, awk et kmod
- Accès root
Fonctionnement
garder = modules chargés maintenant (/proc/modules)
+ tous les modules déjà vus chargés sur l'hôte (/var/lib/kmod-guard/learned)
+ entrées d'autorisation (/etc/kmod-guard/allow.d/*.conf)
+ leurs dépendances (modules.dep, softdep, alias) pour chaque noyau installé
bloquer = modules du noyau en cours - garder
Chaque module bloqué reçoit la ligne install <module> /usr/local/sbin/kmod-guard blocked <module>. Quand quelque chose tente de le charger, modprobe exécute cette commande à la place : la tentative est journalisée dans syslog et le module reste déchargé.
L'ensemble « garder » ne fait que grandir. Relancer generate (manuellement, par minuteur ou par la gestion de configuration) ne peut bloquer que des modules nouveaux pour le noyau en cours.
Installation
git clone https://github.com/webo3/kmod-guard.git
cd kmod-guard
sudo make install
Le script est installé dans /usr/local/sbin/kmod-guard. Ce chemin est fixe, car les lignes install générées l'appellent. L'installation ajoute aussi :
- la liste d'autorisation par défaut dans
/etc/kmod-guard/allow.d/00-managed.conf, si le fichier n'existe pas déjà; - le crochet initramfs pour initramfs-tools ou dracut;
- un service et un minuteur systemd, non activés.
Premier lancement
# Voir ce qui serait bloqué
sudo kmod-guard generate --dry-run
# Écrire la liste
sudo kmod-guard generate
# Régénérer chaque jour
sudo systemctl daemon-reload
sudo systemctl enable --now kmod-guard.timer
Lancez le premier generate une fois que le serveur roule depuis assez longtemps pour que ses services aient chargé leurs modules. L'outil refuse de s'exécuter pendant les 30 premières minutes suivant le démarrage, sauf avec --force.
generate affiche un résumé clé=valeur (nombre de modules gardés et bloqués, nouveaux modules bloqués ou autorisés) qui se termine par result=changed, unchanged, skipped ou disabled. Avec --dry-run, il se termine plutôt par result=dry-run et would_change=yes|no.
Listes d'autorisation
Les fichiers /etc/kmod-guard/allow.d/*.conf doivent appartenir à root et ne pas être modifiables par le groupe ou les autres. Les entrées sont séparées par des espaces; # commence un commentaire.
| Entrée | Correspond à |
|---|---|
xfs |
le module xfs (- et _ sont équivalents) |
nft_*, ip_set* |
un motif sur le nom du module (*, ?) |
path:kernel/drivers/edac/ |
tous les modules dont le chemin sous /lib/modules/<kver>/ commence ainsi |
Inutile de lister les dépendances : autoriser nfs garde aussi sunrpc, lockd, grace, etc.
00-managed.confest destiné à la gestion de configuration.local.confreçoit les ajouts faits sur l'hôte aveckmod-guard allow.- Tout autre fichier
*.confest lu également.
Liste par défaut
La liste par défaut pour serveurs autorise :
- les pilotes matériels et de plateforme, par chemin : ACPI, stockage, cartes réseau, EDAC, cpufreq, hwmon, IPMI, virtio, Hyper-V, Xen, watchdogs, device-mapper;
- les modules hors arbre (
extra/,updates/,weak-updates/) : DKMS, CloudLinux kmod-lve, agents de sauvegarde; - les systèmes de fichiers courants;
- les diagnostics de sockets de
ss; - netfilter (iptables, nftables, ipset), que fail2ban, CSF, Imunify360 et Docker chargent à la première règle.
Restent bloqués, sauf si l'hôte les utilise déjà : les familles de sockets peu courantes, les ordonnanceurs, classificateurs et actions de contrôle du trafic, les périphériques réseau virtuels (vxlan, geneve, macsec…), AF_ALG, les systèmes de fichiers réseau et anciens (cifs, nfs, ceph, 9p, hfs…), les disciplines de ligne tty, RDMA, le son et la vidéo.
Exemples par rôle
Le dépôt fournit des exemples à copier dans /etc/kmod-guard/allow.d/ : Proxmox VE, Docker Swarm et WireGuard.
# Serveur WireGuard : les dépendances (curve25519, chacha20poly1305, udp_tunnel) sont gardées automatiquement
echo "wireguard" | sudo tee /etc/kmod-guard/allow.d/wireguard.conf
sudo kmod-guard generate
Commandes
kmod-guard generate [--dry-run] [--force] [--quiet] [--managed "<entrées>"] [--probe "<modules>"]
kmod-guard allow <module>... autoriser sur cet hôte maintenant (écrit dans allow.d/local.conf)
kmod-guard disable retirer la liste; reste désactivé jusqu'à `kmod-guard enable`
kmod-guard enable
kmod-guard status état, autorisations locales, blocages récents
kmod-guard version
Deux options servent la gestion de configuration :
--managedprévisualise une nouvelle liste gérée sans l'écrire;--proberépond à la question « lesquels de ces modules seraient bloqués ici? ».
Pour charger une seule fois un module bloqué, en tant que root :
sudo modprobe --ignore-install <module>
Vérifier l'exposition à une faille
Quand une faille touchant un module est divulguée, --probe indique si le serveur est protégé. Par exemple, pour les failles de 2026 :
sudo kmod-guard generate --dry-run --probe "algif_aead esp4 esp6 rxrpc act_pedit vsock vsock_loopback openvswitch pppoe cls_flower act_police sctp sctp_diag ah6 tun bridge kvm"
| Faille | CVE | Modules à vérifier |
|---|---|---|
| Copy Fail | CVE-2026-31431 | algif_aead |
| Dirty Frag | CVE-2026-43284, CVE-2026-43500 | esp4 esp6 rxrpc |
| pedit COW | CVE-2026-46331 | act_pedit |
| VsockDrop | CVE-2026-53365 | vsock vsock_loopback |
| OVSwrap | CVE-2026-64531 | openvswitch |
| Zapscape | CVE-2026-64561 | kvm |
| PPPoEject | CVE-2026-68121 | pppoe |
| RtabRace | CVE-2026-68138 | cls_flower act_police |
| bridge-stp-uaf | CVE-2026-72389 | bridge |
| DiagSpill | CVE-2026-74469 | sctp sctp_diag |
| DirtyAH6 | CVE-2026-80844 | ah6 |
| TUNderflow | CVE-2026-81000 | tun |
La ligne probe_blocked= liste les modules qui ne peuvent pas être chargés. Un module absent de cette ligne est chargé ou autorisé sur ce serveur : c'est là qu'il faut appliquer le noyau corrigé en priorité.
Avec la liste par défaut, bridge et kvm restent autorisés, par choix. Ils font partie d'une chaîne de dépendances : bridge est requis par des modules netfilter autorisés (nft_meta_bridge, nft_reject_bridge, nf_conntrack_bridge), et kvm est gardé avec les modules du processeur (path:kernel/arch/x86/). Les bloquer par défaut risquerait de briser un pare-feu ou un hyperviseur. Sur un serveur qui n'en a pas besoin, resserrez la liste d'autorisation.
Journaux
$ journalctl -t kmod-guard
kmod-guard: blocked module=sctp trigger=explicit parent=bash[4121] uid=0 loginuid=1000 cmd=-bash
kmod-guard: blocked module=tipc trigger=autoload parent=kthreadd[2] uid=0 loginuid=unset cmd=
La valeur de trigger indique l'origine :
explicit: un processus a lancémodprobe;udev: un périphérique correspondait;autoload: le noyau a demandé le module lui-même, par exemple viasocket(AF_TIPC, …). La demande passe par un fil du noyau, donc le processus à l'origine ne peut pas être identifié.
Le paramètre BLOCK_EXIT dans /etc/kmod-guard/kmod-guard.conf définit ce que retourne un chargement bloqué :
0(par défaut) :modproberéussit sans rien charger, pour qu'un service qui lancemodprobe foodansExecStartPrecontinue de démarrer;1: le chargement échoue explicitement.
Sécurité de l'outil
- Un module chargé n'est jamais bloqué.
generaterefuse d'écrire une liste qui en bloquerait un (code 70) ou une liste vide. - Le premier passage attend
FIRST_RUN_MIN_UPTIME(1800 s par défaut). - Les dépendances sont résolues pour chaque noyau installé : un nouveau noyau dont les modules dépendent de quelque chose de nouveau l'obtient.
- Les crochets initramfs retirent la liste des images de démarrage, pour qu'un nouveau noyau puisse toujours charger les pilotes du disque racine.
- Les écritures sont atomiques et un fichier inchangé n'est pas réécrit.
Codes de sortie : 64 usage, 65 entrée d'autorisation invalide, 66 modules.dep ou /proc/modules manquant, 70 liste refusée, 77 fichier d'autorisation avec propriétaire ou permissions non sécuritaires.
Limites
kmod-guard n'est pas infaillible : c'est une couche de défense de plus, pas une garantie.
- Certains modules restent autorisés par défaut parce qu'ils font partie d'une chaîne de dépendances (
bridge,kvm). Une chaîne d'attaque peut passer par eux, ou par un module que le serveur utilise réellement. - Root peut toujours charger n'importe quel module avec
insmodoumodprobe --ignore-install. kmod-guard limite ce qu'un utilisateur sans privilèges peut faire entrer dans le noyau; ce n'est pas une frontière contre root (voirkernel.modules_disabledpour cela). - Le code compilé directement dans le noyau (
=y) n'est pas touché. - Autoriser netfilter et le contrôle du trafic garde ce que les espaces de noms utilisateur peuvent atteindre à travers eux. Restreindre ces espaces de noms (
kernel.unprivileged_userns_clone=0,user.max_user_namespacesou AppArmor sur Ubuntu 24.04) est complémentaire. - kmod-guard ne remplace pas les mises à jour du noyau.
Désactiver ou désinstaller
# Désactivation d'urgence : retire la liste jusqu'à `kmod-guard enable`
sudo kmod-guard disable
# Désinstallation (conserve /etc/kmod-guard et /var/lib/kmod-guard)
sudo make uninstall
Code source
Le code est disponible sur GitHub sous licence MIT : github.com/webo3/kmod-guard. L'idée vient de modulejail de Jasper Nuyens; kmod-guard est une implémentation distincte qui ajoute la résolution des dépendances, la mémoire des modules déjà vus et les autorisations par motif et par chemin.
Voici d'autres sujets qui pourrais vous intéréser
Votre site est lent ? Recevez un diagnostic gratuit en 24 h.
Triage gratuit sans engagement. Un expert vous répond en moins de 8 h ouvrables.