Security Advisory – HIGH
Linux Kernel Local Privilege Escalation – Copy Fail (CVE-2026-31431)
Detailed Information
| Severity | HIGH — CVSS 3.1 = 7.8 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
|---|---|
| Disclosure date | 2026-04-29 (public disclosure) |
| Discovery date | 2026-03-23 (reported to Linux kernel security team) |
| Upstream patch date | 2026-04-01 |
| Root cause | Logic flaw in the Linux kernel module crypto/algif_aead, introduced by the in-place AEAD optimization merged in 2017 (commit 72548b093ee3) |
| Affected scope | Linux kernel >= 4.14 (2017) up to (but not including) commit a664bf3d603d (2026-04-01) — every major distribution |
| Vendor status (kernel fix & mitigation notice) | Ubuntu 20.04 / 22.04 / 24.04 / 25.10: kmod mitigation notice released; kernel fix package rolling out via USN (e.g., Ubuntu 22.04: linux-image >= 5.15.0-176-generic) RHEL 8 / 9 / Rocky / Alma: RHSA per stream — check access.redhat.com/security/cve/cve-2026-31431 Debian 11 / 12: DSA backport per the security tracker Amazon Linux 2 / 2023: ALAS per release CloudLinux: KernelCare live-patch released Self-built kernel: see the upstream table in Section 3.1 |
| Quick check | Run uname -r → compare the version against your distro's patched baseline. If < the patched version → VULNERABLE; if >= → SAFE. |
| CVE | CVE-2026-31431 ("Copy Fail") |
| CWE | CWE-669 — Incorrect Resource Transfer Between Spheres |
| Public PoC | Yes — theori-io/copy-fail-CVE-2026-31431 (Python, ~732 bytes) |
| Status | UPSTREAM PATCH AVAILABLE — immediate action required |
| Primary reference | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
1. Incident Summary
The SOC has identified a critical Linux kernel vulnerability — nicknamed "Copy Fail" (CVE-2026-31431) — that allows any local unprivileged user to escalate to root within seconds. The flaw resides in the crypto/algif_aead module, where an in-place AEAD optimization introduced in 2017 lets a user overwrite the page cache of root-owned files via an AF_ALG socket.
IMMEDIATE ACTION REQUIRED
A public PoC is available. Any user with shell access on a vulnerable server can become root within seconds. All Linux hosts (especially multi-tenant systems, K8s workers, and bastions) must apply mitigation or upgrade the kernel within 24 hours.
Two particularly dangerous aspects:
- Containers do not protect you — the bug lives in the host kernel, not the image. Patching the image has no effect.
- An empty
lsmoddoes NOT mean safe — the kernel autoloads the module via MODULE_ALIAS the moment a user creates an AF_ALG socket. Accurate detection must be based on package version.
2. Exploitation Mechanism
The attack abuses the way the kernel processes AEAD operations in-place over the algif_aead interface:
- Abuse the AEAD interface: A local user attacks the
algif_aeadAEAD interface exposed via AF_ALG. No privileges are required — any shell user can do it. - Trigger autoload: The kernel automatically loads the
algif_aeadmodule via MODULE_ALIAS (no CAP_SYS_MODULE needed). - Chain page-cache pages into the destination scatterlist: In certain AF_ALG /
splice()flows, the in-place optimization bug allows page-cache pages (belonging to root-owned files cached by the kernel, e.g.,/etc/shadow) to be placed into the writable destination/output scatterlist. - Trigger in-place AEAD: When the kernel encrypts/decrypts, the output is written onto these very page-cache pages instead of into the user's own buffer — producing a controlled write directly into the page cache of a root-owned file.
- Pivot to full root: A controlled write into the page cache of a privileged file — particularly a setuid binary — leads to Local Privilege Escalation to root.
NVD quote: "There is no benefit in operating in-place in algif_aead since the source and destination come from different mappings. Get rid of all the complexity added for in-place operation and just copy the AD directly."
Patch fix: remove the in-place optimization, ensuring that the destination/output scatterlist of an AEAD operation can no longer be chained with source pages (including page-cache pages) — return to fully out-of-place processing. Fix commit: a664bf3d603d.
Exploit capabilities:
- Local Privilege Escalation from a normal user to root
- Reliable on every major distribution (Ubuntu, RHEL, Debian, Amazon Linux, CloudLinux)
- Tiny PoC (~732 bytes of Python) — easy to embed into a supply-chain attack or to bypass tooling
- No user interaction, no network exposure — purely local
3. Affected Scope
VERY BROAD SCOPE
Every Linux kernel from commit 72548b093ee3 (2017) up to (but not including) commit a664bf3d603d (2026-04-01). All major distributions are affected until the vendor backports the patch.
You may be affected if:
- The server runs a Linux kernel older than your distro's patch date
- A local user can obtain a shell or achieve code execution (web app RCE, supply-chain on a CI runner, etc.)
- K8s nodes run untrusted workloads (multi-tenant clusters)
- Containers can create AF_ALG sockets (the default — no special CAP needed)
3.1 Upstream Kernel Fixed Versions
How to use: run uname -r → take the first two numbers (e.g., 5.15.0-130-generic → series 5.15) → find the matching row → compare the version against the "Safe from" column.
| Kernel series you are running | VULNERABLE if | SAFE if |
|---|---|---|
| 5.10.x | < 5.10.254 | >= 5.10.254 |
| 5.15.x | < 5.15.204 | >= 5.15.204 |
| 6.1.x | < 6.1.170 | >= 6.1.170 |
| 6.6.x | < 6.6.137 | >= 6.6.137 |
| 6.12.x | < 6.12.85 | >= 6.12.85 |
| 6.18.x | < 6.18.22 | >= 6.18.22 |
| 6.19.x | < 6.19.12 | >= 6.19.12 |
| 7.0 (rc) | rc1 → rc6 | rc7 or later |
| Other series (4.14 → 6.18 non-LTS) | any version in the series | must upgrade to one of the patched LTS releases above |
Quick example: uname -r returns 5.15.0-130-generic → series 5.15 → needs >= 5.15.204 → VULNERABLE (patch required).
Note: Distros (Ubuntu / RHEL, etc.) use their own ABI numbering (e.g., Ubuntu's 5.15.0-176-generic), which doesn't match upstream version numbers. The "Patched versions per distro" table at the top of this advisory is the authoritative reference for distros; the table here is for self-built kernels or cross-checks.
4. Detection Indicators
4.1 Module / Runtime Indicators
| Type | Details |
|---|---|
| Module name | algif_aead (same family: algif_skcipher, algif_hash, algif_rng) |
| Module trigger | Creating an AF_ALG socket (autoload via MODULE_ALIAS) |
| Capability required to exploit | NONE (a normal user is sufficient) |
4.2 Process / Behavioral Indicators (Post-Exploit Hunting)
| Type | Details |
|---|---|
| Suspicious syscall pattern | socket(AF_ALG, SOCK_SEQPACKET, 0) from a non-crypto process |
| File integrity | Unusual modifications to /etc/passwd, /etc/shadow, /etc/sudoers not via the typical user-space syscalls |
| Audit log | auditd records a non-root process creating an AF_ALG socket and subsequently escalating privileges |
4.3 References & PoC
| Type | Details |
|---|---|
| NVD entry | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| Ubuntu CVE | https://ubuntu.com/security/CVE-2026-31431 |
| Red Hat advisory | https://access.redhat.com/security/cve/cve-2026-31431 |
| Public PoC | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| Technical writeup | websec.net writeup |
5. Verification Instructions
uname -r
Compare the result against the "Vendor status" table at the top of this advisory (USN / DSA / RHSA / ALAS) or against Table 3.1 (self-built kernel). If the version is below the vendor's patched baseline → VULNERABLE.
Note: On mainstream distros (Ubuntu / RHEL / Debian / Amazon Linux), uname -r returns the vendor-stamped ABI version (e.g., 5.15.0-176-generic) — that's the same string the advisory uses to publish the fixed version, so this check is sufficient. You only need to dig deeper (dpkg -l / rpm -q --changelog / dnf updateinfo info CVE-2026-31431) if you suspect custom ABI numbering or a kernel built from source.
6. Required Remediation
6.1 Immediate Mitigation (No Reboot, < 1 minute)
Block module autoload — a temporary fence while you wait to upgrade the kernel:
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<'EOF' install algif_aead /bin/false EOF
# Rebuild initramfs so the mitigation applies from early boot sudo update-initramfs -u # Debian / Ubuntu sudo dracut -f # RHEL / Fedora / Rocky / Alma
# Unload if currently loaded sudo modprobe -r algif_aead 2>/dev/null || true
# Verify lsmod | grep algif_aead # must be empty sudo modprobe algif_aead 2>&1 # must report "install /bin/false ... failed"
Caveat: The mitigation only blocks algif_aead — the direct exploitation path for this CVE (per public guidance from Ubuntu / Sysdig / Tenable). Workloads that use AF_ALG cipher AEAD (some userspace crypto tools, certain IPSec stacks) will break after the mitigation. Test on a staging host first; after applying, check journalctl | grep -i alg for errors.
6.1.a Alternative: initcall_blacklist via GRUB (if the module is built-in)
If the kernel was built with algif_aead built-in (CONFIG_CRYPTO_USER_API_AEAD=y) instead of as a module, modprobe.d has no effect. Use GRUB to block it at init time:
# Open /etc/default/grub and add "initcall_blacklist=algif_aead_init" to # GRUB_CMDLINE_LINUX. Or use sed: sudo sed -i 's|GRUB_CMDLINE_LINUX="\(.*\)"|GRUB_CMDLINE_LINUX="\1 initcall_blacklist=algif_aead_init"|' /etc/default/grub
# Apply sudo update-grub # Debian / Ubuntu sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL / Rocky / Alma sudo reboot
# Verify after reboot dmesg | grep -i "blacklisting initcall"
6.2 Kernel Upgrade (Reboot Required)
# Ubuntu / Debian sudo apt update sudo apt install --only-upgrade linux-image-generic linux-headers-generic linux-image-virtual sudo reboot
# RHEL / CentOS / Rocky / Alma sudo dnf update kernel sudo reboot
# Amazon Linux 2 sudo yum update kernel && sudo reboot
# Amazon Linux 2023 sudo dnf update kernel && sudo reboot
6.3 Container / K8s Rolling Upgrade
Containers cannot be patched in the image — you must patch the host kernel and reboot each node:
# Get the hostnames (without the "node/" prefix)
NODES=$(kubectl get nodes -o jsonpath='{.items[*].metadata.name}')
for node in $NODES; do
echo "=== $node ==="
kubectl drain "$node" \
--ignore-daemonsets \
--delete-emptydir-data \
--force
ssh "$node" '
sudo apt update
sudo apt install -y --only-upgrade \
linux-image-generic \
linux-headers-generic \
linux-image-virtual
sudo reboot
'
# Wait for the node to come back Ready
until kubectl get node "$node" 2>/dev/null | grep -q ' Ready '; do
sleep 10
done
kubectl uncordon "$node"
done6.3.a Quick Mitigation via DaemonSet (Block the Module — No Reboot)
If you can't yet schedule a rolling reboot, use a DaemonSet to apply Section 6.1 across every node within seconds. This is a stop-gap and DOES NOT replace the kernel upgrade — you still must complete Section 6.3 within your P0/P1 SLA.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: cve-2026-31431-mitigation
namespace: kube-system
spec:
selector:
matchLabels: { app: cve-2026-31431-mitigation }
template:
metadata:
labels: { app: cve-2026-31431-mitigation }
spec:
hostPID: true
tolerations:
- operator: Exists
containers:
- name: mitigate
image: debian:12-slim # needs update-initramfs/modprobe → DO NOT use busybox
command: ["/bin/sh", "-c"]
args:
- |
set -eu
chroot /host /bin/sh -c '
cat > /etc/modprobe.d/disable-algif-aead.conf <<EOF
install algif_aead /bin/false
EOF
update-initramfs -u
modprobe -r algif_aead 2>/dev/null || true
# verify
lsmod | grep algif_aead && exit 1
modprobe algif_aead 2>&1 | grep -q "install /bin/false" || exit 1
echo "[OK] $(hostname) mitigated"
'
sleep infinity
securityContext:
privileged: true
runAsUser: 0
volumeMounts:
- { name: host-root, mountPath: /host }
volumes:
- { name: host-root, hostPath: { path: / } }Verify every node is blocked:
kubectl logs -n kube-system -l app=cve-2026-31431-mitigation --tail=1 --prefix # Each node must print: [OK] <hostname> mitigated
Common pitfalls to avoid:
- ❌
image: busybox— lacksupdate-initramfsand bash → the mitigation does not persist across reboots. - ❌ Forgetting
chroot /host— the script runs in the container's filesystem, not the host's. - ❌ Forgetting
sleep infinity— the pod restarts in a loop and logs become unreadable. - ❌ Blocking the other
algif_*family modules unnecessarily — not required for this CVE, and may break legitimate IPSec/AF_ALG workloads.
6.4 Post-Fix Verification
uname -r # >= 5.15.0-176-generic (Ubuntu 22.04) dpkg -l linux-image-$(uname -r) | tail -1 # Debian/Ubuntu rpm -q kernel # RHEL family lsmod | grep algif_aead # still empty if the mitigation is kept
7. Long-Term Recommendations (Defense-in-Depth)
7.1 Least-Privilege & Access Control
- Least-privilege shell access — only operations users get a real shell. App and service accounts should use
/sbin/nologinor/bin/false. Audit/etc/passwdregularly (getent passwd | awk -F: '$7 ~ /(bash|sh|zsh)$/ {print $1}') to surface user shells outside the expected list. - Hardened bastion / SSH — SSH into production only via a bastion + MFA, never direct SSH from the Internet. Disable password auth, enforce key-based auth + per-user audit trails.
- Network segmentation — production servers should only accept connections from a bastion/jump host or via VPN. Block ingress from the Internet on the SSH port.
- Strict sudo policy — do not grant broad NOPASSWD or
ALL=(ALL); whitelist specific commands instead, and log every sudo invocation via auditd.
8. Support Contact
If your team operates Linux servers and suspects you may be affected, or needs assistance during the verification / mitigation / upgrade process, please contact the SOC for support.
Internal contact: SOC Team
Primary References
- NVD entry
- Ubuntu CVE tracker
- Canonical advisory
- Red Hat advisory
- Amazon Linux ALAS
- CERT-EU 2026-005
- Tenable FAQ
- Sysdig technical analysis
- Help Net Security
- The Register
- websec.net writeup
- Public PoC (theori-io)
- Kernel patch commit
a664bf3d603d