## https://sploitus.com/exploit?id=A22460D4-6E41-5BAD-961E-5282C341077C
# CVE-2026-31431 โ "Copy Fail"
Local Privilege Escalation in the Linux Kernel crypto `algif_aead` subsystem.
## Overview
CVE-2026-31431, dubbed "Copy Fail", is a logic bug in the Linux kernel's `authencesn` cryptographic template (`algif_aead`). It allows an unprivileged local user to perform a controlled 4-byte write into the page cache of any readable file, which can be leveraged to modify a setuid binary and obtain root.
- **CVSS:** 7.8 (High)
- **Affected:** All mainstream Linux kernels shipped since 2017
- **Exploit:** A 732-byte Python script โ no race conditions, no kernel-specific offsets
- **Fix:** Mainline commit `a664bf3d603d`
## Timeline
| Date | Event |
|---|---|
| 2026-03-23 | Reported to Linux kernel security team |
| 2026-04-01 | Patch committed to mainline |
| 2026-04-22 | CVE assigned |
| 2026-04-29 | Public disclosure |
## Impact Matrix
| Environment | `allowPrivilegeEscalation` | Container Root | Host Root | Risk |
|---|---|---|---|---|
| **RHEL 8 / RHEL 9** (local user) | n/a | n/a | **Yes** | **Critical** |
| **OpenShift Node** (shell access, e.g. `oc debug node/`) | n/a | n/a | **Yes** | **Critical** |
| **OpenShift Pod** โ `restricted-v2` SCC (default) | `false` | No | No | **Low** |
| **OpenShift Pod** โ `anyuid` SCC | `true` | **Yes** | No (namespace isolation) | **High** |
| **OpenShift Pod** โ `privileged` SCC | `true` | **Yes** | **Yes** (no isolation) | **Critical** |
| **OpenShift Pod** โ custom SCC | depends | depends | depends | **Audit** |
| **Kubernetes Pod** โ PSS Restricted | `false` | No | No | **Low** |
| **Kubernetes Pod** โ PSS Baseline / no policy | `true` (default) | **Yes** | No | **High** |
| **Docker / Podman** โ `--security-opt no-new-privileges` | `false` | No | No | **Low** |
| **Docker / Podman** โ default | `true` | **Yes** | No | **High** |
The exploit requires two things: an `AF_ALG` socket (allowed by default in all seccomp profiles) and a setuid binary (e.g. `/usr/bin/su`). The key mitigation is `allowPrivilegeEscalation: false` โ this sets the Linux kernel's [`no_new_privs`](https://docs.kernel.org/userspace-api/no_new_privs.html) flag via `prctl(PR_SET_NO_NEW_PRIVS, 1)`, which causes the kernel to ignore setuid/setgid bits on `execve()`. Since the exploit relies on executing a modified setuid binary, this blocks the final escalation step.
This is **not an OpenShift-specific feature** โ it works the same way on vanilla Kubernetes (Pod Security Standards Restricted), Docker (`--security-opt no-new-privileges`), and Podman. OpenShift simply enforces it by default via the `restricted-v2` SCC, while other platforms require explicit configuration.
### RHEL 8 / RHEL 9
RHEL 8 and RHEL 9 ship kernels that contain the vulnerable code. An unprivileged local user with shell access can exploit this to gain root. **Patch immediately.**
```bash
yum updateinfo list cves CVE-2026-31431
yum update kernel
```
### OpenShift (4.x)
OpenShift runs on RHCOS, which ships the vulnerable kernel. The practical impact depends on the workload's Security Context Constraints (SCC).
Standard workloads using the default `restricted-v2` SCC are **not exploitable** because `allowPrivilegeEscalation: false` is enforced.
Pods running with elevated SCCs (`anyuid`, `privileged`, or custom SCCs allowing `allowPrivilegeEscalation: true`) **are vulnerable**. This commonly includes:
- CI/CD build pods (Jenkins agents, Tekton with custom SCCs)
- Legacy applications requiring `anyuid`
- Infrastructure pods (monitoring, logging, storage)
Direct node access (e.g. via `oc debug node/`) is always vulnerable โ standard local privilege escalation, no container isolation involved.
## Testing
A test pod is provided to check whether the exploit prerequisites are met in your cluster. It does **not** attempt to exploit the vulnerability โ it only checks:
1. Can an `AF_ALG` socket be created? (kernel attack surface reachable)
2. Is `no_new_privs` set? (blocks setuid escalation)
3. Are setuid binaries present in the container image?
4. Kernel version of the underlying node
### Usage
```bash
oc apply -f test-pod.yaml
oc logs cve-2026-31431-check
oc delete -f test-pod.yaml
```
### Exit codes
| Code | Meaning |
|---|---|
| `0` | Not exploitable โ AF_ALG socket blocked by seccomp |
| `1` | Partially exposed โ AF_ALG reachable but setuid blocked by `no_new_privs` |
| `2` | Vulnerable โ all exploit prerequisites are met |
### Expected result on default OpenShift
On a standard OpenShift cluster with `restricted-v2` SCC, you should see exit code `1` (partially exposed): the AF_ALG socket can be created (RuntimeDefault seccomp does not block it), but `no_new_privs` prevents the setuid escalation step. The published PoC will not work, but the kernel-level vulnerability is still reachable โ patching is recommended.
## Mitigation
### 1. Patch the kernel (P0)
This is the only complete fix. Update the kernel on all nodes and reboot.
For OpenShift, update to a RHCOS version that includes the fix and perform a rolling node reboot.
### 2. Disable algif_aead module (interim workaround)
If `algif_aead` is compiled as a **loadable module** (`CONFIG_CRYPTO_USER_API_AEAD=m`):
```bash
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true
```
**This does NOT work if `algif_aead` is built-in (`=y`)**, which is the case on RHCOS. Check with:
```bash
modinfo algif_aead 2>&1 | grep builtin
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
```
### 3. Block AF_ALG via seccomp (OpenShift)
If the kernel module is built-in, the only pre-patch mitigation for containers is blocking the `socket(AF_ALG, ...)` syscall via a custom seccomp profile.
#### Deploy the seccomp profile via MachineConfig
Create the MachineConfig to place the profile on all nodes (repeat with `role: master` for control plane nodes):
```yaml
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 99-worker-seccomp-deny-af-alg
spec:
config:
ignition:
version: 3.2.0
storage:
files:
- path: /var/lib/kubelet/seccomp/deny-af-alg.json
mode: 0644
contents:
source: data:application/json;charset=utf-8;base64,ewogICJkZWZhdWx0QWN0aW9uIjogIlNDTVBfQUNUX0FMTE9XIiwKICAic3lzY2FsbHMiOiBbCiAgICB7CiAgICAgICJuYW1lcyI6IFsic29ja2V0Il0sCiAgICAgICJhY3Rpb24iOiAiU0NNUF9BQ1RfRVJSTk8iLAogICAgICAiYXJncyI6IFsKICAgICAgICB7CiAgICAgICAgICAiaW5kZXgiOiAwLAogICAgICAgICAgInZhbHVlIjogMzgsCiAgICAgICAgICAib3AiOiAiU0NNUF9DTVBfRVEiCiAgICAgICAgfQogICAgICBdCiAgICB9CiAgXQp9
```
The base64 content decodes to:
```json
{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [
{
"names": ["socket"],
"action": "SCMP_ACT_ERRNO",
"args": [
{
"index": 0,
"value": 38,
"op": "SCMP_CMP_EQ"
}
]
}
]
}
```
> **Note:** Applying a MachineConfig triggers a rolling node reboot.
#### Reference the profile in pod specs
```yaml
securityContext:
seccompProfile:
type: Localhost
localhostProfile: deny-af-alg.json
```
#### Cluster-wide alternative
To protect all containers without modifying pod specs, override the CRI-O default seccomp profile (`/etc/crio/seccomp.json`) via MachineConfig by adding the AF_ALG filter rule to the existing profile.
### 4. Audit your SCCs
Identify pods running with elevated privileges:
```bash
# Find pods not using restricted-v2
oc get pods -A -o json | jq -r '
.items[] |
select(.metadata.annotations["openshift.io/scc"] != "restricted-v2") |
"\(.metadata.namespace)/\(.metadata.name) โ \(.metadata.annotations["openshift.io/scc"])"
'
```
These are the pods where the full exploit chain works. Prioritize patching or seccomp mitigation for nodes running these workloads.
## Impact of disabling AF_ALG
Blocking AF_ALG sockets has **negligible impact** on most workloads. The following are **not affected**:
- dm-crypt / LUKS
- kTLS
- IPsec
- OpenSSL / GnuTLS (standard builds)
Only applications explicitly configured to use the OpenSSL `afalg` engine will be affected.
## References
- [Copy Fail โ Project Page](https://copy.fail)
- [Red Hat CVE-2026-31431](https://access.redhat.com/security/cve/cve-2026-31431)
- [NVD โ CVE-2026-31431](https://nvd.nist.gov/vuln/detail/CVE-2026-31431)
- [RuntimeDefault does not block AF_ALG (juliet.sh)](https://juliet.sh/blog/we-tested-copy-fail-in-kubernetes-pss-restricted-runtime-default-af-alg)
- [Xint โ Copy Fail Write-Up](https://xint.io/blog/copy-fail-linux-distributions)
- [The Register โ Linux cryptographic code flaw](https://www.theregister.com/2026/04/30/linux_cryptographic_code_flaw/)