Responsive defense layer for Linux. Ships kernel-LPE mitigations as 0days land, closing the window between public CVE disclosure and the vendor patch reaching your hosts (or a fleet reboot becoming available). Signed yum/dnf repo for EL7/EL8/EL9/EL10, 4-hourly auto-update cron, zero reboot required for any mitigation. New bug classes ship with each release. Install once, stay covered.
Today's shipping coverage: 7 LPE classes across two families. Copy Fail page-cache writes (cf1 / CVE-2026-31431, cf2 / Dirty Frag-ESP / CVE-2026-43284, DF-RxRPC / CVE-2026-43500, Fragnesia, PinTheft / CVE-2026-43494, DirtyDecrypt / CVE-2026-31635); FD-theft via SUID exit-race (ssh-keysign-pwn / CVE-2026-46333). See coverage matrix for per-class rung detail.
Six defense-in-depth rungs in one dnf install: LD_PRELOAD
shim, modprobe blacklists, per-unit systemd drop-ins, host-wide userns
+ ptrace + io_uring sysctls, auditd tripwires, and a read-only posture
auditor. Auto-detection at install time suppresses any drop-in that
would break a detected workload (IPsec, AFS, rootless containers,
Flatpak, firejail, desktop browsers, Oracle RDS / HPC, io_uring
consumers); every other layer stays active.
copyfail-defense) or v1.x
(afalg-defense)?
sudo dnf upgrade -y rfxn-defense handles every prior
layout (rename, file splits, new subpackages) automatically. State
under /var/lib/copyfail-defense/ and /etc/copyfail/
migrates to the rfxn-defense paths via %pretrans
mv -n (idempotent). SIEM queries must update the audit-key
prefix (copyfail_* → rfxn_*). Review
journalctl -t rfxn-defense-detect afterward to see what
was suppressed. Shim activation remains the explicit operator step
(rfxn-shim-enable).
copyfail.repo
in /etc/yum.repos.d/ will 404 on
dnf check-update after v3.0.0 ships:
sudo curl -sSL https://rfxn.github.io/rfxn-defense/rfxn-defense.repo \
-o /etc/yum.repos.d/rfxn-defense.repo
sudo rm -f /etc/yum.repos.d/copyfail.repo
sudo dnf upgrade -y rfxn-defense
A single rfxn-defense.repo file works for EL7/EL8/EL9/EL10:
dnf expands $releasever + $basearch per host.
RPMs are GPG-signed and the metadata itself is verified via detached
repomd.xml.asc (gpgcheck=1 +
repo_gpgcheck=1).
sudo curl -sSL https://rfxn.github.io/rfxn-defense/rfxn-defense.repo \ -o /etc/yum.repos.d/rfxn-defense.repo sudo dnf install -y rfxn-defense sudo /usr/sbin/rfxn-shim-enable
The 4-hourly auto-update cron (-autoupdate subpackage,
pulled by the meta) keeps the host current; new mitigations land within
4 hours of a release tag with no operator action. Opt out by touching
/etc/rfxn-defense/auto-update.disabled.
The meta pulls seven subpackages (-audit as soft dep on
EL8/9/10, hard dep on EL7 since rpm-4.11 has no Recommends:):
| Subpackage | Coverage |
|---|---|
rfxn-defense-shim |
LD_PRELOAD AF_ALG block (cf1 primary) |
rfxn-defense-modprobe |
kernel-module entry-point cuts (cf1, cf2, Dirty Frag, PinTheft, DirtyDecrypt) |
rfxn-defense-systemd |
per-unit RestrictAddressFamilies=~AF_ALG AF_KEY AF_RXRPC AF_RDS + RestrictNamespaces=~user net on user@/sshd/cron/crond/atd; container-runtime + RDS opt-in examples (v3.0.1 fixed deny-list syntax: only the first token carries the ~) |
rfxn-defense-sysctl |
host-wide user.max_user_namespaces=0 (suppressed on rootless / Flatpak / firejail / browser); kernel.yama.ptrace_scope=2 (always-applied independent drop-in since v3.0.1); kernel.io_uring_disabled=2 (Linux 6.6+ only, suppressed on io_uring workloads) |
rfxn-defense-auditor |
read-only host posture auditor (rfxn-local-check) covering 7 bug classes with per-class layer breakdown |
rfxn-defense-audit |
auditd tripwires (rfxn_afalg/afkey/afrxrpc/afrds/pidfd_getfd) |
rfxn-defense-autoupdate |
/etc/cron.d/rfxn-defense-autoupdate + flock-protected /usr/sbin/rfxn-defense-update wrapper |
Which rung blocks which bug class. ✓ = primary mitigation, applied without caveat; ✓ n = active coverage with a kernel- or workload-conditional caveat (see footnote); n alone = detection only, no mitigation (see footnote); · = not applicable.
| Mitigation rung | cf1 | cf2 | DF-ESP | DF-RxRPC 6 | Fragnesia | PinTheft | keysign-pwn |
|---|---|---|---|---|---|---|---|
LD_PRELOAD shim (AF_ALG hook) |
✓ | · | · | ✓ ¹ | · | · | · |
modprobe algif_aead family |
✓ ² | · | · | · | · | · | · |
modprobe esp4 esp6 xfrm_user xfrm_algo |
· | ✓ | ✓ | · | ✓ | · | · |
modprobe rxrpc |
· | · | · | ✓ | · | · | · |
modprobe rds rds_tcp rds_rdma |
· | · | · | · | · | ✓ ⁴ | · |
systemd RestrictAddressFamilies=~AF_ALG |
✓ | · | · | · | · | · | · |
systemd RestrictAddressFamilies=~AF_KEY |
· | ✓ | ✓ | · | ✓ | · | · |
systemd RestrictAddressFamilies=~AF_RXRPC |
· | · | · | ✓ | · | · | · |
systemd RestrictAddressFamilies=~AF_RDS |
· | · | · | · | · | ✓ | · |
systemd RestrictNamespaces=~user ~net |
· | ✓ | ✓ | · | ✓ | · | · |
sysctl user.max_user_namespaces=0 |
· | ✓ | ✓ | · | ✓ | · | · |
sysctl kernel.yama.ptrace_scope=2 (always-on, v3.0.1) |
· | · | · | · | · | · | ✓ |
sysctl kernel.io_uring_disabled=2 |
· | · | · | · | · | ✓ ⁵ | · |
| auditd tripwire rules | ³ | ³ | ³ | ³ | ³ | ³ | ³ |
1 Catches the cksum step in the public DF-RxRPC
PoC, not the kernel sink itself; defense-in-depth, not a primary stop.
2 No-op on RHEL stock kernels (CRYPTO_USER_API*
built-in). Supported workaround: grubby --update-kernel ALL
--args "initcall_blacklist=algif_aead_init" + reboot.
3 Detection only, not mitigation. Telemetry for
socket(AF_ALG/AF_KEY/AF_RXRPC/AF_RDS) and
pidfd_getfd from unprivileged users. Highest value on
hosts where modprobe blacklists are auto-suppressed (IPsec / AFS /
Oracle RDS workloads) and the kernel sink stays reachable. Query via
ausearch -k rfxn_{afalg,afkey,afrxrpc,afrds,pidfd_getfd}.
4 Functional on Ubuntu/Debian/Arch kernels and ELRepo
kernel-ml swaps where rds.ko is loadable. No-op on stock
RHEL/Alma/Rocky/Oracle UEK kernels (no CONFIG_RDS=m).
Auto-suppressed on Oracle Grid / HPC hosts (signals:
/etc/oratab, crsctl, loaded rds*.ko).
5 Auto-applied on Linux 6.6+ hosts where no io_uring
workload is detected (liburing.so in /proc/*/maps,
known-consumer binaries, io_uring-named systemd units). Suppressed on
rootless / Flatpak / container-runtime hosts and kernels < 6.6.
Override: CFD_FORCE_IOURING_DISABLE=1 rfxn-redetect or
CFD_SUPPRESS_IOURING_DISABLE=1 rfxn-redetect.
6 DirtyDecrypt (CVE-2026-31635, rxgk_* RXGK
token-decrypt in-place crypto) is cross-stamped onto the DF-RxRPC
column: every AF_RXRPC mitigation that covers DF-RxRPC also covers
DirtyDecrypt.
-audit subpackage)| Key | Signature |
|---|---|
rfxn_afalg |
socket(AF_ALG=38) by unprivileged user (cf1) |
rfxn_afkey |
socket(AF_KEY=15) by unprivileged user (cf2 / DF-ESP / Fragnesia) |
rfxn_afrxrpc |
socket(AF_RXRPC=33) by unprivileged user (DF-RxRPC / DirtyDecrypt) |
rfxn_afrds |
socket(AF_RDS=21) by unprivileged user (PinTheft) |
rfxn_pidfd_getfd |
pidfd_getfd() syscall 438 by unprivileged user (ssh-keysign-pwn) |
Rules ship at /etc/audit/rules.d/99-rfxn-defense.rules
with auid≥1000 filter on every key. The auditor probes
page-cache integrity for /usr/bin/su,
/usr/libexec/openssh/ssh-keysign, and the PAM stacks each
class targets, as a cached-IOC for an in-flight exploit. See
--json posture.bug_classes[*].kernel_sink.
Flagged via --emit-remediation; no subpackage applies them,
since each can break legitimate workloads on a busy fleet. Review before
pasting.
| Action | Targets | When recommended |
|---|---|---|
chmod 4750 /usr/bin/su && chgrp wheel /usr/bin/su |
cf2, DF-ESP | Suppressed when non-wheel/admin interactive users exist (cPanel-style tenant fleets); chmod 4750 would break their su workflow. |
auditd rule cf_userns (unshare(CLONE_NEWUSER)) |
cf2, DF-ESP | Hosts where auditd is tuned for userns events (otherwise high alert noise). |
auditd rule cf_addkey (add_key("rxrpc",...)) |
DF-RxRPC | Always; rxrpc keyring activity is rare enough that the false-positive rate stays low. |
The installer inspects the host in %posttrans and
suppresses any drop-in that would break a detected
workload. Every other layer stays active. The cf1 LD_PRELOAD
shim and audit tripwires are never suppressed, so cf1
(CVE-2026-31431)
coverage is unchanged on every host.
| Workload | Signals (any of) | Suppresses |
|---|---|---|
| IPsec (strongSwan, libreswan, openswan) | enabled systemd unit (strongswan/libreswan/openswan/ipsec/pluto); /etc/ipsec.conf conn stanza; non-empty *.conf under /etc/swanctl/conf.d/, /etc/ipsec.d/, /etc/strongswan{,/conf.d}/ |
99-cf2-xfrm.conf (esp4, esp6, xfrm_user, xfrm_algo blacklist). cf2/DF-ESP still blocked via the systemd RestrictNamespaces=~user ~net unshare gate. |
| AFS (openafs, kafs) | enabled systemd unit (openafs-client/server, kafs, afsd); /etc/openafs/{CellServDB,ThisCell}; /etc/krb5.conf.d/openafs*; /proc/fs/afs/ registered |
99-rxrpc.conf + 12-rxrpc-af.conf (~AF_RXRPC on all 5 tenant units). DF-RxRPC residual coverage: auditd rfxn_afrxrpc tripwire. |
| Rootless containers (rootless podman/buildah) | /home/*/.local/share/containers/storage/overlay-containers/ (mtime ≤ 180d); /var/lib/containers/storage/overlay-{containers,images}/ or vfs-{containers,images}/ contains a non-lockfile entry (v3.0.1: tightened from "any non-empty subdir" to require a real container or image, ruling out storage-tree init by podman package install); /run/user/<UID≥1000>/containers/; podman.socket enabled (system or per-user) |
15-userns.conf on user@.service only + host-wide userns sysctl. sshd/cron/crond/atd keep RestrictNamespaces=~user net. kernel.yama.ptrace_scope=2 is NOT affected (own drop-in since v3.0.1). |
| Userns consumers (Flatpak, firejail, desktop browser) | non-empty /var/lib/flatpak/{app,runtime} or per-user ~/.local/share/flatpak/app (mtime ≤ 180d); /usr/bin/firejail; /usr/bin/{chromium,chromium-browser,google-chrome,firefox,firefox-esr} |
99-rfxn-defense-userns.conf host-wide sysctl only; per-unit RestrictNamespaces stays active. |
| RDS workload (Oracle Grid Infrastructure, HPC) | /etc/oratab non-comment non-blank entry; **/grid/bin/crsctl under /u01/app/oracle or /opt/oracle; any of /sys/module/{rds,rds_tcp,rds_rdma} currently loaded |
99-rfxn-defense-rds.conf modprobe drop only; tenant-unit ~AF_RDS stays applied; rfxn_afrds auditd tripwire stays loaded. |
| io_uring workload | liburing.so in /proc/*/maps; known consumer binary executable (postgres, scylla, mariadbd, dockerd, redis-server, nginx, envoy, rabbitmq-server); io_uring-named systemd unit |
99-rfxn-defense-iouring.conf only. PinTheft primary cut (RDS modprobe) stays applied. |
False-positive guards: /etc/subuid populated by
useradd is not a rootless signal
(shadow-utils auto-populates it for every regular user, which produced
~100% FPs on cPanel-shaped fleets in v2.0.1 rev 1). Rootful container
signal requires mtime < 90d. /home walk
bounded (maxdepth 6, mtime -180).
/run/user/<UID>/containers requires UID ≥ 1000.
sudo cat /var/lib/rfxn-defense/auto-detect.json sudo journalctl -t rfxn-defense-detect --since today sudo rfxn-local-check --json | jq '.posture.auto_detect'
auto-detect.json (schema v2) lists
detected.<workload>.signals,
suppressed.<dropin>, and
applied.<dropin> flags for every drop-in the
installer manages. Detection runs in %posttrans after
every install/upgrade and on demand via rfxn-redetect.
# Re-run detection after enabling IPsec/AFS/rootless post-install sudo /usr/sbin/rfxn-redetect sudo systemctl daemon-reload sudo systemctl try-reload-or-restart sshd.service sudo sysctl --system # if any sysctl drop-in was added or removed # Skip detection entirely - apply every drop-in unconditionally sudo mkdir -p /etc/rfxn-defense sudo touch /etc/rfxn-defense/force-full sudo /usr/sbin/rfxn-redetect
The auditor reports force-full sentinel active when the
sentinel is on. Remove the file and re-run rfxn-redetect
to re-engage detection.
# cf1: AF_ALG socket creation should fail python3 -c 'import socket; socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)' # expect: PermissionError [Errno 1] Operation not permitted # ssh-keysign-pwn: ptrace_scope should be 2 on hardened host cat /proc/sys/kernel/yama/ptrace_scope # expect: 2 # Holistic per-class coverage report sudo rfxn-local-check # tail-of-output: # Surface area / mitigation matrix: # Class Sink reachable? Mitigated? Active layers # cf1 (CVE-2026-31431) YES yes ld_preload_shim, systemd_af_alg, modprobe_blacklist # cf2 (xfrm-ESP) YES yes modprobe_blacklist, systemd_restrict_ns # Dirty Frag-ESP YES yes modprobe_blacklist, systemd_restrict_ns # Dirty Frag-RxRPC YES yes modprobe_blacklist, systemd_af_rxrpc # PinTheft (AF_RDS) YES yes rds_modprobe, af_rds_restrict, rfxn_afrds # keysign-pwn (ptrace) YES yes ptrace_scope, rfxn_pidfd_getfd
systemd drop-ins use the standard layered-override pattern: within a
<unit>.service.d/ directory, files merge in lex order
and lower numbers lose to higher numbers for
=value directives. rfxn-defense ships at 10-,
12-, 15-; operator escape hatches sit at
20- and 25-.
20-override.conf (neutralize a directive).
Empty = clears the union for list-valued directives.
Survives package upgrade (operator-owned, RPM does not manage it):
sudo install -d /etc/systemd/system/user@.service.d sudo tee /etc/systemd/system/user@.service.d/20-override.conf >/dev/null <<'EOF' [Service] RestrictNamespaces= RestrictAddressFamilies= EOF sudo systemctl daemon-reload
25-additions.conf (add a directive on top
of ours). Sorts after 20-:
sudo tee /etc/systemd/system/sshd.service.d/25-additions.conf >/dev/null <<'EOF' [Service] NoNewPrivileges=true EOF sudo systemctl daemon-reload sudo systemctl try-reload-or-restart sshd.service
modprobe override: conditional cf2-xfrm.conf
and rxrpc.conf are managed by detect.sh (cmp-and-skip).
Hand-edit and detect.sh logs a WARN on the next
%posttrans/rfxn-redetect and
preserves your edits. The always-on
cf1.conf is %config(noreplace). Do not
chattr +i a managed file: it breaks dnf via EPERM on
install -m 0644.
{
"schema_version": "2.0",
"covers": ["cf1", "cf2", "dirtyfrag-esp", "dirtyfrag-rxrpc", "pintheft", "keysign-pwn"],
"posture": {
"verdict": "vulnerable_kernel_userspace_mitigated",
"bug_classes_covered": ["cf1", "cf2", "dirtyfrag-esp", "pintheft", "keysign-pwn"],
"bug_classes": {
"cf1": { "applicable": true, "mitigated": true, "layers": {} },
"pintheft": { "applicable": true, "mitigated": true, "layers": { "rds_modprobe": true, "af_rds_restrict": true, "io_uring_disabled": true } },
"keysign-pwn": { "applicable": true, "mitigated": true, "layers": { "ptrace_scope": true, "pidfd_getfd_auditd": true } }
},
"auto_detect": { "available": true, "suppressed_modprobe": [], "suppressed_systemd": [] }
}
}
bug_classes_covered is the SIEM-ergonomic single filter
("is this host hardened?"). bug_classes exposes per-layer
breakdown for finer dashboards. verdict and layers
from v1.0.x are preserved for backwards compat. Exit codes (unchanged):
0 clean, 2 VULN, 3
VULN-but-mitigated, 4 hardening recommendations only.
Each release on
github.com/rfxn/rfxn-defense/releases
ships per-EL binary RPMs, an SRPM, the .repo file, and the
public signing key as release assets. v3.0.2 is the current line; older
v3.0.0 / v3.0.1 / 2.0.x / 2.1.x RPMs are archived under
repo/N/x86_64/archive/ in the dnf repodata so
dnf upgrade resolves cleanly from any installed version.
The .repo file (works on EL7/EL8/EL9/EL10):
sudo curl -sSL https://rfxn.github.io/rfxn-defense/rfxn-defense.repo \ -o /etc/yum.repos.d/rfxn-defense.repo
The public signing key (dnf imports automatically on first install; pre-import for offline verification):
sudo curl -sSL https://rfxn.github.io/rfxn-defense/RPM-GPG-KEY-rfxn \ | sudo rpm --import /dev/stdin
Per-EL binary RPMs are independently compiled against each
distribution's glibc (EL7: 2.17 split libdl;
EL8: 2.28 split libdl; EL9/EL10: 2.34+ merged
libdl). Do not cross-install across ELs.
| File | sha256 |
|---|---|
| rfxn-defense-3.0.2-1.el7.x86_64.rpm | 8f77d9f780190cc119a086ccd6412cd8f10c6c20b7aa64b17b4c2c7e8049c948 |
| rfxn-defense-audit-3.0.2-1.el7.noarch.rpm | 491eb8a04efde5c5863cc9c4d92f8a5b8d23189ce32f3b0a6f94063ecb98ea0d |
| rfxn-defense-auditor-3.0.2-1.el7.noarch.rpm | e8f534b8779ff2e36a64c246c84f4147aaa4bff07d4f9f09a9bd12ae4d426053 |
| rfxn-defense-autoupdate-3.0.2-1.el7.noarch.rpm | a7ea637ee8270a4c2b5e67245c75f6b81ab3fa45c9e01732c74eb2258a1fa255 |
| rfxn-defense-modprobe-3.0.2-1.el7.noarch.rpm | 81d3b922d9f7cb36d543f556e5c64e0f68c87d702cf11c4a863fc63b7b23b56c |
| rfxn-defense-shim-3.0.2-1.el7.x86_64.rpm | bb179e2c7654b6ed4e8da4fe88836b911030f4242f5bd9f04633d3d9a1ba24be |
| rfxn-defense-sysctl-3.0.2-1.el7.noarch.rpm | d143dc30a1b57e2b529bc19d0b59a46ec540b8640935a46c67841a2ef2fb6990 |
| rfxn-defense-systemd-3.0.2-1.el7.noarch.rpm | 3c2f8bb8a44a5bd3dc462ad2631dbaaa51b14f1f2c54aefd9095ca76590f1fe0 |
| rfxn-defense-3.0.2-1.el7.src.rpm | 517c25d7032e76d1bebacb0fb1a0e3f65b6abde0ea2b75d5abf8463cf93909f9 |
| File | sha256 |
|---|---|
| rfxn-defense-3.0.2-1.el8.x86_64.rpm | efd42dd8d071421c21dfd307320e0ef2b99bee4a30d7510e22dac57539371542 |
| rfxn-defense-audit-3.0.2-1.el8.noarch.rpm | 50b8a9be6ba6ff2a6e8c427d97be91f8253b14829b672fced46e625ea2843524 |
| rfxn-defense-auditor-3.0.2-1.el8.noarch.rpm | 150f42b877d7c3b054002100ef399db759531c587f7ad9df4713e2a2c93a76ae |
| rfxn-defense-autoupdate-3.0.2-1.el8.noarch.rpm | cc47306e220390f5565e339173bfd97411bf8e870615c9856456a118c7fbd7cd |
| rfxn-defense-modprobe-3.0.2-1.el8.noarch.rpm | 95e7b001d3b7cfd3529c55bd33b707cac68ece616a457f25b53c10a3a84f6d30 |
| rfxn-defense-shim-3.0.2-1.el8.x86_64.rpm | 9715db9bfc8ff4c99183f638c0847b5f6235265e56ab1b459ae8cb95f392e91b |
| rfxn-defense-sysctl-3.0.2-1.el8.noarch.rpm | 15b59442af3093d45351fc917cee812eab64a5ccd196f0c3875c076ee454edee |
| rfxn-defense-systemd-3.0.2-1.el8.noarch.rpm | cf42b0266d8ed40c28b8dea5f1091fdd0128706d465fcf51981a2c6ac8bc7437 |
| rfxn-defense-3.0.2-1.el8.src.rpm | 3bf05c48fa78d2cfbe819f557b939e12c79fa1eb8e7ffe45d1180f5593fdc8b1 |
| File | sha256 |
|---|---|
| rfxn-defense-3.0.2-1.el9.x86_64.rpm | 379a21e8cc6198e92c39109f26e043b19bdace9254112d2db29202503bf3e5aa |
| rfxn-defense-audit-3.0.2-1.el9.noarch.rpm | 8152b328cbe64fbab4fb701bfb22780e4f9bf29d6c57b186931159df31854c45 |
| rfxn-defense-auditor-3.0.2-1.el9.noarch.rpm | 795b0a776b12e066e948d1c1e3949fb7ed8ffd3edc1b37fd117964c746e88d2e |
| rfxn-defense-autoupdate-3.0.2-1.el9.noarch.rpm | 5de34329a105fbe9f1f6347e87dabbbc538dc1260a74cb1fdcb6f378f92bfd40 |
| rfxn-defense-modprobe-3.0.2-1.el9.noarch.rpm | 3af3b411af4828937908e77b3948431dba7eeb9bdd95880395f68dc8d7e8d217 |
| rfxn-defense-shim-3.0.2-1.el9.x86_64.rpm | 52916845017ccc0c674e05e05c60aae9bcaeb416f713ad28f27223bcf9ac5b36 |
| rfxn-defense-sysctl-3.0.2-1.el9.noarch.rpm | dd44ab6e8d737b1a421a12a3b300dcc4abf401ed2d808afd7d40d87752af66c6 |
| rfxn-defense-systemd-3.0.2-1.el9.noarch.rpm | bec85dd0897280e43aec1e0e490ccbd21dc5c3b9201b8dd73c5a031dcfbe3b7c |
| rfxn-defense-3.0.2-1.el9.src.rpm | 2e29a3f34d22a92f2cac34b11932d9eafa61370d7004b8eea0ac04c501de937b |
| File | sha256 |
|---|---|
| rfxn-defense-3.0.2-1.el10.x86_64.rpm | fec9f133b123fbbd1bfaea85736f8620c4890159edb188b0e234877f88f06ac7 |
| rfxn-defense-audit-3.0.2-1.el10.noarch.rpm | c5c0db5ef103be35879f33104a3fab0d8b81afdd954fc4ca935809613e461626 |
| rfxn-defense-auditor-3.0.2-1.el10.noarch.rpm | 78dbd678b2e209d36e07985483c582e34867b9ac033b4e792dbb6ca4a3f4e7c4 |
| rfxn-defense-autoupdate-3.0.2-1.el10.noarch.rpm | 0672dd4317b5bc83c0bacefa513728138a80a2e186bd7f00bbde88ac5aa7876f |
| rfxn-defense-modprobe-3.0.2-1.el10.noarch.rpm | 8b9cd054342f5694118a560eaddb379720f4c72e0bfc312e71ec68d26cf23e96 |
| rfxn-defense-shim-3.0.2-1.el10.x86_64.rpm | 320ba68792c474f0f1a0f123836e96c95f01f9fc06dbe7a0ab0cd7d36c73cee7 |
| rfxn-defense-sysctl-3.0.2-1.el10.noarch.rpm | a22e6b8b2d946e13d2f9cda5ee985c1d26189c2ae453727802ade37d520caa5f |
| rfxn-defense-systemd-3.0.2-1.el10.noarch.rpm | 6d4b18a6cf540e95bb98f48fb5b8b2d7e3b931df6ac4228806c9de4af52b9459 |
| rfxn-defense-3.0.2-1.el10.src.rpm | 9e8f1262f2a07ee5a042d068778d0c3491edd7ffed1e3cf10896557bdab0c08f |
v1.0.1 and later are signed by the Copyfail Project Signing Key (retained as the project's canonical signing identity through the v3.0.0 rfxn-defense rename):
fingerprint: 6001 1CDC EA2F F52D 975A FDEE 6D30 F32C D5E8 0F80
uid: Copyfail Project Signing Key <proj@rfxn.com>
key file: /RPM-GPG-KEY-rfxn
(legacy alias: /RPM-GPG-KEY-copyfail, identical content)
The rfxn-defense.repo sets both gpgcheck=1
(verifies each RPM) and repo_gpgcheck=1 (verifies
repomd.xml via the detached repomd.xml.asc
we publish alongside it). dnf imports the public key from
gpgkey= on first use.
Verify out-of-band:
curl -sSL https://rfxn.github.io/rfxn-defense/RPM-GPG-KEY-rfxn | gpg --import gpg --fingerprint proj@rfxn.com # expect: 6001 1CDC EA2F F52D 975A FDEE 6D30 F32C D5E8 0F80 rpm --import https://rfxn.github.io/rfxn-defense/RPM-GPG-KEY-rfxn rpm -K /path/to/rfxn-defense-3.0.2-1.el9.x86_64.rpm # expect: digests signatures OK
Each rung defeats the bug by a different mechanism, so an attack that defeats one does not necessarily defeat the next.
| Rung | Where it fails | What the next rung covers |
|---|---|---|
| Kernel patch (vendor) | EL7 EOL; rollout on supported ELs lags disclosure days-to-weeks; reboot may not be available; DF-RxRPC, PinTheft, ssh-keysign-pwn have no upstream patch as of v3.0.0 | Userspace cuts close the window without a reboot; rfxn-defense is a kernel-patch-free coverage path |
modprobe blacklist |
No-op when relevant module is builtin (RHEL algif_aead); no effect on already-resident modules |
Functional for esp4/esp6/xfrm_user/xfrm_algo/rxrpc/rds* on stock RHEL kernels |
systemd RestrictAddressFamilies / RestrictNamespaces |
Reaches only services systemd starts post-restriction. Misses cron-as-root, sshd-pre-restriction, container payloads with own pid 1, interactive shell exploit binary | Host-wide userns sysctl catches the interactive-shell case; LD_PRELOAD shim covers every dyn-linked process regardless of init |
| Host-wide userns / ptrace / io_uring sysctls | Auto-suppressed on rootless / Flatpak / firejail / browsers (userns); io_uring workloads; pre-6.6 kernels (io_uring). In-flight processes retain a userns they already grabbed | Per-unit RestrictNamespaces still applies on tenant units; auditd logs post-suppression userns prep |
| LD_PRELOAD shim | Static binaries; direct syscall instruction; SUID strip |
seccomp at unit/runtime level catches direct-syscall path |
| auditd tripwire rules | Detection only, not mitigation. Fails when auditd is not running or rules are unloaded | Becomes the residual signal on hosts where modprobe blacklists are auto-suppressed (IPsec / AFS / RDS workloads) and the kernel sink stays reachable |
Where the shim itself fails (static binaries, direct syscall,
SUID stripping) is attacker engineering territory. The
other rungs fail under routine operator reality:
vendors haven't shipped yet, the kernel was built with builtin crypto,
the threat surface includes a cron job. That asymmetry is the case
for deploying every rung.
Per-release notes (full detail): github.com/rfxn/rfxn-defense/releases. Per-commit history: github.com/rfxn/rfxn-defense/commits.
| Version | Date | Summary |
|---|---|---|
| v3.0.2 | 2026-05-24 | EL7 silent-failure closure. Empirically validated against a
fresh CentOS 7.9.2009 VM (systemd 219, procps-ng 3.3.10,
kernel 3.10). Critical: systemd v219 (EL7)
silently ignores RestrictNamespaces= (added in
v235); the userns drop-in shipped on every prior 3.0.x build
was inert at unit-start on EL7. Critical:
EL7 procps-ng 3.3.10 mis-parses the sysctl.d(5)
-key silent-skip prefix (added in 3.3.12), so
every key in 99-rfxn-defense-ptrace.conf and
99-rfxn-defense-userns.conf silently no-op'd
- ssh-keysign-pwn (CVE-2026-46333) primary mitigation
latent on every EL7 host. Both layers now distro-gated; the
ptrace_scope sysctl dropped the - prefix.
Critical: %posttrans sysctl
loop omitted ptrace.conf entirely -
replaced with sysctl --system so the file
actually applies at install time on every distro. Auditor:
systemd_restrict_namespaces no longer silent-
SKIPs on EL7 (now emits explicit "predates v235" reason or
FAIL with stale drop-in list); userns_sysctl OK
message distinguishes "blocked by rfxn drop-in" from "blocked
by kernel/distro default"; ptrace_scope
remediation text points at the correct file (was stale from
v3.0.0). New packaging/test-el7-live.sh live-host
runner with 33 assertions including empirical mitigation
probes that isolate each layer. |
| v3.0.1 | 2026-05-24 | Fixup release validated against live cPanel + admin hosts.
Critical: systemd drop-in deny-list syntax
was ~A ~B ~C (parse-fail; RestrictNamespaces
silently became no and ~AF_KEY / ~AF_RDS
denial never applied); fixed to ~A B C.
kernel.yama.ptrace_scope=2 split into its own
always-applied drop-in (was bundled in userns file and lost
with any rootless/Flatpak/firejail/browser suppression).
Rootless detector Signal 2 tightened to require a real
container/image artifact (overlay-containers/* non-lockfile),
ruling out podman-installed-but-unused hosts. Auditor fixes:
recognises auditctl -l hex format
(a0=0x26) by matching key=rfxn_*;
credits the LD_PRELOAD shim under cf1 instead of misreporting
n/a; banner updated to 7-class coverage. |
| v3.0.0 | 2026-05-23 | Project rename copyfail-defense →
rfxn-defense; reframe as general-purpose responsive
defense layer. New -autoupdate subpackage: 4-hourly
cron + flock wrapper, lands new mitigations within 4 hours of a
release tag. DirtyDecrypt (CVE-2026-31635) cross-stamped onto
DF-RxRPC coverage. Double Obsoletes/Provides chain handles v2.x
upgrade; state migrates via %pretrans mv -n. |
| v2.1.1 | 2026-05-23 | io_uring sysctl promoted from opt-in to auto-applied with
layered suppression. New
99-rfxn-defense-iouring.conf drop-in (Linux 6.6+
only). Older RPMs moved to repo/N/x86_64/archive/. |
| v2.1.0 | 2026-05-22 | PinTheft (CVE-2026-43494) Copy Fail extension via RDS + io_uring;
ssh-keysign-pwn (CVE-2026-46333) FD-theft class.
kernel.yama.ptrace_scope=2 sysctl;
rfxn_afrds + rfxn_pidfd_getfd auditd
rules. EL7 build target via vault.centos.org. |
| v2.0.2 | 2026-05-13 | Fragnesia / Dirty Frag-ESP coverage. New
-sysctl subpackage
(user.max_user_namespaces=0); new
-audit subpackage (~AF_KEY closes the
PF_KEYv2 SA-config path). CVE cross-stamping for cf2
(CVE-2026-43284) and DF-RxRPC (CVE-2026-43500). |
| v2.0.1 | 2026-05-08 | Workload auto-detection: IPsec / AFS / rootless-container
suppression in %posttrans; per-host state at
/var/lib/rfxn-defense/auto-detect.json. File-layout
split (3 modprobe files, 3 systemd drop-in layers). |
| v2.0.0 | 2026-05-08 | Umbrella rename afalg-defense →
copyfail-defense; expanded to the Copy Fail bug
class. New -modprobe and -systemd
subpackages. |
| v1.0.1 | 2026-04-29 | Initial signed release. afalg-defense-shim
(LD_PRELOAD AF_ALG block) and
afalg-defense-auditor (read-only host posture
auditor). RPMs and repodata GPG-signed. |
Bugs, packaging problems, false positives, missing distros: please
file a
GitHub issue. Include the auditor's --json output if
the report is about detection, and the output of
uname -a + cat /etc/os-release for any
runtime question.