Share
## 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/)