Fedora Account System
Red Hat Associate
Red Hat Customer
Spec URL: https://jforbes.fedorapeople.org/modulejail/modulejail.spec SRPM URL: https://jforbes.fedorapeople.org/modulejail/modulejail-1.6.2-1.fc46.src.rpm Description: ModuleJail snapshots the set of currently loaded modules and writes a modprobe.d blacklist for every kernel module not currently in use, minus a built-in baseline and an optional sysadmin-supplied whitelist. Aimed at Linux fleet operators who need to harden many servers against the wave of AI-assisted kernel privilege-escalation discoveries. Every additional loaded module is additional latent attack surface for the next disclosed CVE. No daemon, no continuous monitoring, no AI inside the tool. One shell script, run once on a steady-state host, that writes one modprobe.d blacklist file. Fedora Account System Username: jforbes
https://koji.fedoraproject.org/koji/taskinfo?taskID=150604967 scratch build
Hi, upstream author here. Thanks Justin for packaging this. Some context for whoever picks up the review: * Debian already ships it. 1.6.1-1 is in unstable and testing (ITP #1138266). * I'm happy to change things upstream if it makes the Fedora package cleaner: - %post runs "modulejail --install-initramfs-hook", which writes /usr/lib/dracut/modules.d/99modulejail-strip/ at install time. The hook keeps the blacklist out of the initramfs. Otherwise dracut bakes the current blacklist into the initramfs on a kernel update, and if the new kernel renames a storage driver the machine could fail to boot (upstream issue #19). Dropping it from the initrd costs no security, since no unprivileged users exist before pivot_root. Right now no package owns those files. I can add a way to generate the hook at build time so the spec ships it in %files instead. - The script runs an update check against api.github.com after each run (MODULEJAIL_NO_UPDATE_CHECK turns it off). I can add a build-time switch so distro packages ship with the check disabled. * Source0 can point at https://github.com/jnuyens/modulejail/archive/v%{version}/%{name}-%{version}.tar.gz If anything else comes up, reply here or open an issue on GitHub and I'll respond quickly. Jasper
Hi Justin, Both changes are in 1.6.3: 1. Package the dracut hook and drop %post/%preun: %install ./modulejail --install-initramfs-hook --initramfs-builder dracut --destdir %{buildroot} %files %dir %{_prefix}/lib/dracut/modules.d/99modulejail-strip %{_prefix}/lib/dracut/modules.d/99modulejail-strip/module-setup.sh 2. Disable the GitHub update check: sed -i 's/^UPDATE_CHECK_DEFAULT=1$/UPDATE_CHECK_DEFAULT=0/' %{buildroot}%{_bindir}/modulejail Tested on Fedora 45: rpm -V is clean, an upgrade from 1.6.2 takes over the old hook file, removal deletes it, and the hook strips the blacklist from hostonly images. Source0: https://github.com/jnuyens/modulejail/archive/v1.6.3/modulejail-1.6.3.tar.gz Thanks, Jasper
Package was updated: SRPM URL: https://jforbes.fedorapeople.org/modulejail/modulejail-1.6.3-1.fc46.src.rpm Scratch build: https://koji.fedoraproject.org/koji/taskinfo?taskID=151723906 spec URL doesn't change.
For lack of a better review tool, I've posted my suggestions as a diff below with notes inline. For convenience, the full spec is at https://jcline.fedorapeople.org/new-packages/modulejail.spec and you can fetch all the sources with "spectool -g modulejail.spec". None of these are particularly deal-breaking, so if there's something you don't like that's fine. Name: modulejail Version: 1.6.3 -Release: 1%{?dist} +Release: %{autorelease} I'm lazy and don't care to manually bump the release, this should be paired with %{autochangelog} Summary: Shrink Linux kernel-module attack surface License: GPL-3.0-only URL: https://modulejail.com -Source0: %{name}-%{version}.tar.gz +Source0: https://github.com/jnuyens/modulejail/archive/v%{version}/%{name}-v%{version}.tar.gz This way you can bump the version and run spectool -g on the specfile to fetch the new sources +Source1: https://github.com/jnuyens/modulejail/releases/download/v%{version}/v%{version}.tar.gz.sig +# The repository documents the signing key ID is 095F 5C8B 39AF 010E 7B61 5CD4 487B C00D 69C2 A955 +# +# At the time I fetched this, the following signing key was present: +# +# sq inspect --cert=095F5C8B39AF010E7B615CD4487BC00D69C2A955 --keyring ./jnuyens.gpg +# OpenPGP Certificate. +# +# Fingerprint: 095F5C8B39AF010E7B615CD4487BC00D69C2A955 +# Public-key algo: RSA +# Public-key size: 4096 bits +# Creation time: 2026-05-24 19:26:07 UTC +# Key flags: certification, signing +Source2: https://github.com/jnuyens.gpg Upstream does sign their releases, so pulling in the signature and signing key lets us check that. You can check in the keyfile rather than uploading it as a source if you'd prefer, but either way you'll see if it changes during the normal update workflow. BuildArch: noarch +BuildRequires: openpgpverify Requires: coreutils Requires: findutils Requires: gawk Recommends: curl -%description +%global _description %{expand: ModuleJail snapshots the set of currently loaded modules and writes a modprobe.d blacklist for every kernel module not currently in use, minus a built-in baseline and an optional sysadmin-supplied whitelist. @@ -25,90 +40,39 @@ No daemon, no continuous monitoring, no AI inside the tool. One shell script, run once on a steady-state host, that writes one modprobe.d -blacklist file. +blacklist file.} + +%description %{_description} + This is a silly hack to handle the description macro needing to either be one line or escaping the line breaks %prep -%setup -q +%{openpgpverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' +%autosetup -n %{name}-%{version} -p1 + Verify the signature and use autosetup - if you drop in "Patch: some.patch" at the top it'll apply them which is convenient. + +%build +sed -i 's/__VERSION__/%{version}/' man/modulejail.8.in +sed -i "s/__DATE__/$(date -u -d @${SOURCE_DATE_EPOCH} +%Y-%m-%d)/" man/modulejail.8.in +# Updates are shipped via dnf +sed -i 's/^UPDATE_CHECK_DEFAULT=1$/UPDATE_CHECK_DEFAULT=0/' modulejail + Disable updates and set the version and date in the manpage. This seems to be all the build script upstream does. %install install -Dm755 modulejail %{buildroot}%{_bindir}/modulejail -install -Dm644 README.md %{buildroot}%{_docdir}/%{name}/README.md -install -Dm644 LICENSE %{buildroot}%{_docdir}/%{name}/LICENSE -install -Dm644 modulejail.8 %{buildroot}%{_mandir}/man8/modulejail.8 +install -Dm644 man/modulejail.8.in %{buildroot}%{_mandir}/man8/modulejail.8 These days you don't need to manually install files referenced in %doc or %license, they're handled automagically. # Stage the dracut strip hook so the package owns it (see gh #19 and # docs/DEFENSE-IN-DEPTH.md). It keeps the blacklist out of rebuilt # initramfs images; dracut picks it up on the next kernel install. ./modulejail --install-initramfs-hook --initramfs-builder dracut --destdir %{buildroot} -# Distro repositories ship updates through dnf, so a distro build would -# also turn off the post-run GitHub update check here: -# sed -i 's/^UPDATE_CHECK_DEFAULT=1$/UPDATE_CHECK_DEFAULT=0/' %%{buildroot}%%{_bindir}/modulejail -# This upstream package is installed from GitHub releases, so it keeps it. + %files +%license LICENSE +%doc README.md %{_bindir}/modulejail -%dir %{_docdir}/%{name} -%doc %{_docdir}/%{name}/README.md -%license %{_docdir}/%{name}/LICENSE %{_mandir}/man8/modulejail.8* %dir %{_prefix}/lib/dracut/modules.d/99modulejail-strip %{_prefix}/lib/dracut/modules.d/99modulejail-strip/module-setup.sh %changelog -* Tue Oct 27 2026 Justin M. Forbes <jforbes> - 1.6.3-1 -- Initial Fedora packaging - -* Mon May 18 2026 Jasper Nuyens <jnuyens> - 1.6.3-1 -- Add --whitelist-file PATH flag (closes GitHub Issue #2). Reads a - site-local whitelist file (one module per line, # comments, blank - lines ignored), validates each line against [a-zA-Z0-9_-]+, refuses - group- or world-writable files, and appends valid names to the - in-script WHITELIST. Operators no longer lose site-local additions - on .deb/.rpm/curl|sh reinstalls. -- Add --no-syslog-logging flag. Default behaviour change: when - /usr/bin/logger is executable on the host, generated install lines - now call logger with tag 'modulejail' so blocked module loads are - visible via 'journalctl -t modulejail' or 'grep modulejail - /var/log/syslog'. --no-syslog-logging restores the v1.1.4 - /bin/true install-line body byte-for-byte. -- Add archived v1.1.4 regression fixture under - tests/fixtures/v1.1.4-regression/, exercising the body-identical - invariant as a permanent baseline. - -* Wed May 13 2026 Jasper Nuyens <jnuyens> - 1.1.4-1 -- Add project logo to README. -- Test infra: update container fixture to be version-agnostic (was - hardcoded to 1.0.0 strings) and add four new assertions covering the - v1.1.x update-check surface, including a static regression guard - against the v1.1.2 busybox-wget bug. - -* Wed May 13 2026 Jasper Nuyens <jnuyens> - 1.1.3-1 -- Update check now works on Alpine / busybox wget. The wget invocation - used GNU long-form flags (--quiet, --max-redirect=5, - --output-document=-) that busybox wget rejects, causing the check to - silently exit non-zero on every Alpine host. Switched to the - universal short-flag subset (-q, -T 10, -O -) and dropped - --max-redirect (the GitHub tags API does not redirect). No other - changes. - -* Wed May 13 2026 Jasper Nuyens <jnuyens> - 1.1.2-1 -- Adds modulejail(8) manpage; ships at /usr/share/man/man8/modulejail.8.gz. - -* Tue May 12 2026 Jasper Nuyens <jnuyens> - 1.1.1-1 -- Documentation: swap the order of "Why?" and "What ModuleJail is" in - the README so the motivation leads. -- Packaging: drop the per-distro %dist suffix from the RPM filename - (was modulejail-X.Y.Z-1.el9.noarch.rpm, now - modulejail-X.Y.Z-1.noarch.rpm). ModuleJail is a noarch shell script - with no per-major-RHEL semantics. - -* Tue May 12 2026 Jasper Nuyens <jnuyens> - 1.1.0-1 -- Adds .deb and .rpm packaging. -- Adds optional post-run check for a newer release on GitHub: silent on - any failure, 10-second hard timeout, only complains when reachable - and a newer tag exists. Honours MODULEJAIL_NO_UPDATE_CHECK. - -* Tue May 12 2026 Jasper Nuyens <jnuyens> - 1.0.1-1 -- Documentation cleanup release. - -* Tue May 12 2026 Jasper Nuyens <jnuyens> - 1.0.0-1 -- Initial release. +%{autochangelog} If you use this, the changelog is pulled from the git commit. To save this existing log, write it to a "changelog" file in the repository (https://jcline.fedorapeople.org/new-packages/modulejail-1.6.3-1.fc46.src.rpm has it as an example).