Share
## https://sploitus.com/exploit?id=A5EC936E-7FE0-56D9-9D7A-997CF9440079
# CVE-2026-31431 Seccomp Mitigation

A lightweight, reversible seccomp-based mitigation for CVE-2026-31431, a local privilege escalation vulnerability in the Linux kernel’s `algif_aead` / `authencesn` crypto subsystem. Uses a **PAM module** to apply seccomp filters at session open time, covering ALL session types: `su`, `ssh`, `login`, and more. ---

# CVE-2026-31431 Seccomp Mitigation Solution

A lightweight, reversible seccomp-based mitigation for CVE-2026-31431. This vulnerability is a local privilege escalation issue in the Linux kernel’s `algif_aead` / `authencesn` crypto subsystem. The mitigation employs a **PAM module** to apply seccomp filters during session creation, covering all session types: `su`, `ssh`, `login`, etc. ---

## Vulnerability Overview / Vulnerability Description

### Type: Local Privilege Escalation (LPE)

### Affected Component: Linux kernel `crypto/algif_aead.c` – in-place AEAD operation

### Attack Principle: A 4-byte controllable write can be made to any readable file’s page cache via the `authencesn` AEAD algorithm’s scratch-write path. By targeting `/etc/passwd`, an attacker can change the UID to 0 (root) and gain a root shell via `su`. **Affected Kernels:** Confirmed on kernels 6.12+, 6.17+, 6.18+, and also reproduced on RHEL/CentOS 4.18 kernels. **Root Cause:** The commit `72548b093ee3` introduced an in-place AEAD operation. When spliced page-cache pages are used as the destination scatterlist, the AAD `seqno_lo` field is incorrectly written back into the page-cache during AEAD decryption. **Upstream Fix:** Reverted to an out-of-place AEAD operation. ###

### Type: Local Privilege Escalation (LPE)

### Affected Component: Linux kernel `crypto/algif_aead.c` – in-place AEAD operation

### Attack Principle: A 4-byte controllable write can be made to the page cache of any readable file via the `authencesn` AEAD algorithm’s scratch-write path. By targeting `/etc/passwd`, an attacker can change the UID to 0 (root) and gain a root shell via `su`. **Affected Kernels:** Confirmed on kernels 6.12+, 6.17+, 6.18+, and also reproduced on RHEL/CentOS 4.18 kernels. **Root Cause:** The commit `72548b093ee3` introduced an in-place AEAD operation. When spliced page-cache pages are used as the destination scatterlist, the AAD `seqno_lo` field is incorrectly written back into the page-cache during AEAD decryption. **Upstream Fix:** Reverted to an out-of-place AEAD operation. ###

## How This Mitigation Works / How the Mitigation Works

This solution consists of **two components**:

1. **PAM Module (`pam_block_afalg.so`)** – The primary defense. It is loaded by PAM during session opening (`pam_sm_open_session`). It applies a seccomp BPF filter that blocks `socket(AF_ALG,...)` before any user code runs. This covers ALL PAM-authenticated sessions: `su -c`, `su -`, SSH, TTY login, etc. 2. **Standalone Binary (`block_afalg`)** – Optional. It can be used for specific programs in non-PAM scenarios (e.g., cron jobs, systemd services, manual invocations). The seccomp filter:
 - Blocks only `socket(AF_ALG,...)` (returning EACCES)
 - Has zero impact on all other system calls (including `setuid`, `su`, `sudo`)
 - Is inherited by all child processes (fork + exec)
 - Automatically detects patched kernels and acts as a no-op. ###

## Architecture / Architecture

```
PAM session opening (su, ssh, login, etc.)
 |
 v
pam_block_afalg.so (pam_sm_open_session)
 |
 +-- Check: Is the kernel vulnerable? (Try `socket(AF_ALG)`)
 | |
 | +-- No → Return PAM_SUCCESS (no-op)
```

| |
 | +-- Yes --> prctl(PR_SET_SECCOMP, BPF filter)
 | |
 | +-- seccomp filter active on sshd child process
 | +-- inherited by user's shell and ALL child processes
 | +-- socket(AF_ALG,...) returns EACCES
 v
User's shell / command runs with seccomp protection
 |
 +-- su, sudo, and all other syscalls work normally
 +-- Only AF_ALG socket is blocked
```

## Files / 

| File | Purpose |
|------|---------|
| `pam_block_afalg.c` | PAM module source. Applies seccomp filter at session open. |
| `pam_minimal.h` | Minimal PAM type definitions (compiles without pam-devel). |
| `block_afalg.c` | Standalone seccomp wrapper binary. For non-PAM use. |
| `deploy.sh` | Deployment script. Compiles, installs, and manages the PAM module. |
| `README.md` | This file. |

## Requirements / 

- Linux kernel with seccomp support (most modern kernels)
- `gcc` (for compilation)
- `libpam` (runtime, usually pre-installed)
- Root/sudo access (for installation)
- x86_64 architecture (BPF filter uses x86_64 syscall numbers)

## Quick Start / 

```bash
# 1. Compile PAM module
gcc -Wall -O2 -fPIC -shared -o pam_block_afalg.so pam_block_afalg.c \
 /usr/lib64/libpam.so.0

# 2. Install
sudo cp pam_block_afalg.so /lib64/security/
sudo chmod 755 /lib64/security/pam_block_afalg.so

# 3. Activate - APPEND to PAM configs (important: use >>, not sed -i '1i')
echo 'session optional pam_block_afalg.so' | sudo tee -a /etc/pam.d/su
echo 'session optional pam_block_afalg.so' | sudo tee -a /etc/pam.d/sshd
echo 'session optional pam_block_afalg.so' | sudo tee -a /etc/pam.d/login

# 4. Verify (must be a NEW session - existing sessions are not affected)
# Open a new SSH connection or su session, then:
cat /proc/self/status | grep Seccomp
# Should show: Seccomp: 2

python3 -c "
import socket
try:
 s = socket.socket(38,2,0); s.close()
 print('VULNERABLE')
except OSError:
 print('BLOCKED')
"
# Should show: BLOCKED

# 5. Uninstall
sudo rm /lib64/security/pam_block_afalg.so
sudo sed -i '/pam_block_afalg/d' /etc/pam.d/su /etc/pam.d/sshd /etc/pam.d/login
```

## Important Notes / 

### PAM Config Placement / PAM 

**Always APPEND the module to the end of PAM configs.** Never insert at the top. ** PAM 。 ** 。 ** Incorrect /:
```bash
# DON'T - this breaks SELinux and other required session modules
sudo sed -i '1i session optional pam_block_afalg.so' /etc/pam.d/sshd
```

Correct /:
```bash
# DO - append to the end
echo 'session optional pam_block_afalg.so' | sudo tee -a /etc/pam.d/sshd
```

Placing the module before `pam_selinux.so` or other `required` session modules can break authentication and privilege escalation (su/sudo). `pam_selinux.so` `required` session (su/sudo)。 ### Existing Sessions / 

The seccomp filter is applied at session open time. **Existing sessions started before the module was installed are NOT affected.** You must log out and log back in for the protection to take effect. seccomp 。 **。** 。 ```bash
# Check if current session is protected / 
cat /proc/self/status | grep Seccomp
```

# Seccomp: 0 = not protected (old session) 
# Seccomp: 2 = protected (new session with module) 

### PR_SET_NO_NEW_PRIVS / PR_SET_NO_NEW_PRIVS Issue 

The module **does NOT** set `PR_SET_NO_NEW_PRIVS`. This flag prevents `setuid` transitions, which would break `su` and `sudo`. Since PAM modules run as root (with `CAP_SYS_ADMIN`), the seccomp filter can be loaded without this flag. The filter is still inherited by all child processes. The module **does NOT** set `PR_SET_NO_NEW_PRIVS`. This flag prevents `setuid` transitions, causing `su` and `sudo` to fail. Since PAM modules run as root (with `CAP_SYS_ADMIN`), the seccomp filter can be loaded without this flag. The filter is still inherited by all child processes. 

## Command Reference / 

| Command | Description | |
|---------|-------------|------|
| `deploy.sh install` | Compile PAM module, install it to `/lib64/security/`, create an uninstall script | PAM , `/lib64/security/`, |
| `deploy.sh remove` | Complete uninstall: removes the module, cleans PAM configurations, deletes files | :、 PAM 、 |
| `deploy.sh status` | Shows installation status, PAM configurations, kernel status | 、PAM 、 |

## Design Principles / 

### Covers All Session Types / 

The PAM module approach ensures protection for: 
- `su - user -c "command"` (the previously bypassed case) 
- `su - user` (interactive login) 
- SSH sessions 
- TTY/console login 
- Any other PAM-authenticated session 

PAM modules ensure that the following scenarios are protected: 
- `su - user -c "command"` (the previously bypassed case) 
- `su - user` (interactive login) 
- SSH sessions 
- TTY/console login 
- All other PAM-authenticated sessions 

### Minimal Impact / 

- **Single syscall filter:** Only `socket(AF_ALG,...)` is blocked. All other system calls work normally. 
- **No user shell modification:** Users keep their original login shell. 
- **No system package modification:** Only a `.so` file is added to `/lib64/security/`. 
- **Optional PAM configuration:** Use the `optional` flag so that login never fails due to the module. 
- **`su/sudo` unaffected:** `setuid` operations work normally. 

### Reversibility / 

- `deploy.sh remove` completely cleans up: removes the module binary, removes PAM configuration entries, deletes all files. 
- Or manually: `sudo rm /lib64/security/pam_block_afalg.so && sudo sed -i '/pam_block_afalg/d' /etc/pam.d/su /etc/pam.d/sshd /etc/pam.d/login` 
- No persistent changes remain after cleaning. 
- Existing sessions retain their seccomp filter until they end. 

### Kernel Upgrade Safety / 

- The PAM module checks every session to see if the kernel is still vulnerable. 
- If the kernel has been patched (e.g., AF_ALG socket creation fails), the module acts as if it’s inactive. 
- No manual intervention is required after kernel upgrades. 

### Standalone Usage / 

For non-PAM scenarios, use `block_afalg` directly: 

```bash
# Compile / 
gcc -Wall -O2 -o block_afalg block_afalg.c 

# Run a command with AF_ALG blocked / AF_ALG 
```./block_afalg python3 your_script.py./block_afalg bash

## Verification / 

### Check if the kernel is vulnerable / 

```bash
python3 -c"
import socket
try:
 s = socket.socket(38, socket.SOCK_SEQPACKET, 0)
 s.close()
 print('VULNERABLE: AF_ALG socket available')
except:
 print('SAFE: AF_ALG socket blocked or unavailable')
"
```

### Verify that the PAM module is active / PAM 

```bash
# Check seccomp status / seccomp 
cat /proc/self/status | grep Seccomp
# Seccomp: 0 = not protected
# Seccomp: 2 = protected

# Test AF_ALG socket / AF_ALG 
python3 -c"
import socket
try:
 s = socket.socket(38,2,0)
 s.close()
 print('AF_ALG available - NOT protected')
except OSError:
 print('AF_ALG blocked - PROTECTED')
"
```

### Check PAM logs / PAM 
grep pam_block_afalg /var/log/secure
# Should show: seccomp filter applied, AF_ALG blocked

## Troubleshooting / 

### su/sudo not working after installing the module / su/sudo 

This was caused by `PR_SET_NO_NEW_PRIVS` in earlier versions. The current version does NOT use this flag. Update the module:

This was caused by `PR_SET_NO_NEW_PRIVS` in earlier versions. The current version does NOT use this flag. Update the module:

```bash
gcc -Wall -O2 -fPIC -shared -o pam_block_afalg.so pam_block_afalg.c /usr/lib64/libpam.so.0
sudo cp pam_block_afalg.so /lib64/security/
```

### The module is placed at the top of the PAM configuration / PAM 

This breaks `pam_selinux.so` and other required modules. Move it to the end:

This will break `pam_selinux.so` and other required modules. Move it to the end:

```bash
sudo sed -i '/pam_block_afalg/d' /etc/pam.d/sshd
echo 'session optional pam_block_afalg.so' | sudo tee -a /etc/pam.d/sshd
```

### Existing sessions are not protected / 

The seccomp filter is applied at session creation. Log out and log back in:

The seccomp filter is applied at session creation. Log out and log back in:

```bash
# Exit the current session
exit
# Reconnect
ssh user@host
# Verify
cat /proc/self/status | grep Seccomp
```

## Limitations / 

- **Only x86_64:** The BPF filter hardcodes the system call number 41 (`__NRSocket` on x86_64). Other architectures require updating the system call number. - **PAM-dependent:** Only protects sessions that pass through PAM. Direct `exec()` calls without PAM are not covered (use `block_afalg` for those). - **No runtime disable:** Once the seccomp filter is applied to a process, it cannot be removed. The kernel ensures it’s only applied when needed. - **Only new sessions:** Existing sessions started before the module installation are not retroactively protected. x86_64:
- BPF 41(x86_64 `__NRSocket`)。 。 PAM:
- PAM 。 PAM `exec()` ( `block_afalg` )。 :
- seccomp 。 。 :
- 。 ## When to Remove / 

1. **Official kernel patches are applied** - The PAM module automatically detects this, but you can still remove it using `remove`. 2. **RHEL/CentOS releases a patched kernel** - `yum update kernel` will then remove the module. :
1. **** - PAM ,。 2. **RHEL/CentOS ** - `yum update kernel` 。 ## License / 

This tool is provided for authorized security testing and defensive purposes only. Use it only on systems you own or are explicitly authorized to assess. 。 。