Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
57c2bcc
kernelCTF: add CVE-2026-23231_cos
AIS0127 May 1, 2026
ab6d131
kernelCTF: enable separate KASLR leak for exp449
AIS0127 May 3, 2026
0ed62df
kernelCTF: improve exp449 repro and verifier
AIS0127 May 4, 2026
500acc8
kernelCTF: clean up exp449 gadget offsets and unused code
AIS0127 May 16, 2026
a714522
kernelCTF: remove reclaim from exp449 KASAN verifier path
AIS0127 May 22, 2026
c982f1e
kernelCTF: restore exp449 poison reclaim verifier
AIS0127 May 25, 2026
791de6e
kernelCTF: tune exp449 verifier flood count
AIS0127 May 25, 2026
007243e
kernelCTF: shrink exp449 exploit binary
AIS0127 May 26, 2026
d8aedac
kernelCTF: preserve exp449 debug symbols
AIS0127 May 26, 2026
1f57c80
ci: rerun exp449 checks
AIS0127 May 26, 2026
cc0bbda
kernelCTF: increase exp449 vuln-trigger flooders
AIS0127 May 26, 2026
18e99c3
ci: rerun exp449 checks
AIS0127 May 26, 2026
6666804
kernelCTF: tune exp449 verifier and race flooders
AIS0127 May 27, 2026
68783d6
ci: rerun exp449 checks
AIS0127 May 27, 2026
e3a45b7
kernelCTF: extend exp449 verifier and alias races
AIS0127 May 30, 2026
0a72530
kernelCTF: stabilize exp449 verifier and repro races
AIS0127 May 30, 2026
b6649f6
ci: rerun exp449 checks
AIS0127 May 30, 2026
7350666
ci: rerun exp449 checks
AIS0127 May 30, 2026
526a298
kernelCTF: speed up exp449 verifier trigger
AIS0127 May 30, 2026
88f68cd
kernelCTF: isolate exp449 verifier races
AIS0127 May 30, 2026
727d668
kernelCTF: split exp449 verifier race profiles
AIS0127 May 30, 2026
104d2a1
kernelCTF: restore exp449 LPE race pacing
AIS0127 May 30, 2026
7b2eec7
kernelCTF: use legacy exp449 verifier race
AIS0127 May 30, 2026
2506a08
kernelCTF: extend exp449 verifier race budget
AIS0127 May 30, 2026
00be4ae
kernelCTF: restore exp449 single verifier race
AIS0127 May 30, 2026
3aa46b8
kernelCTF: speed up exp449 verifier trigger
AIS0127 May 30, 2026
a97b711
kernelCTF: mix exp449 verifier race profiles
AIS0127 May 30, 2026
a743bcc
kernelCTF: widen exp449 vuln trigger retries
AIS0127 May 30, 2026
3a32444
kernelCTF: restore exp449 6.1 verifier profile
AIS0127 May 30, 2026
a558713
Revert "kernelCTF: restore exp449 6.1 verifier profile"
AIS0127 May 30, 2026
cb59572
Revert "kernelCTF: widen exp449 vuln trigger retries"
AIS0127 May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 221 additions & 0 deletions pocs/linux/kernelctf/CVE-2026-23231_cos/docs/exploit.md

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions pocs/linux/kernelctf/CVE-2026-23231_cos/docs/vulnerability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Vulnerability: Use-After-Free in nf_tables_addchain() Error Path (CVE-2026-23231)

## Summary

A use-after-free vulnerability exists in the netfilter `nf_tables` subsystem, specifically in the error path of `nf_tables_addchain()`. If hook registration fails after the chain has been published, the error path calls `nft_chain_del()` and then immediately calls `nf_tables_chain_destroy()` without an intervening `synchronize_rcu()`.

This violates the RCU publish/grace-period/free contract and creates two separate UAF conditions covered by CVE-2026-23231:

- **Control-plane UAF**: `nf_tables_dump_chains()` traverses `table->chains` under `rcu_read_lock()`, so a concurrent dump can still walk the chain after it has been removed with `list_del_rcu()` but before readers quiesce.
- **Packet-path UAF**: for `NFPROTO_INET`, `nf_register_net_hook()` can briefly install the IPv4 hook before IPv6 registration fails. Packets entering `nft_do_chain()` through that transient IPv4 hook can still dereference `chain->blob_gen_X` after the chain has been freed.

The exploit in this submission uses the second condition: partial `NFPROTO_INET` hook registration failure caused by exhausting IPv6 `LOCAL_OUT` hooks.

## Affected Component

- **Subsystem**: netfilter / nf_tables
- **Source file**: `net/netfilter/nf_tables_api.c`
- **Function**: `nf_tables_addchain()`

## Vulnerability Type

- **Cause**: Use-After-Free (UAF) due to missing RCU grace period
- **Root cause**: `nf_tables_addchain()` frees the chain immediately after `list_del_rcu()` on the hook-registration failure path, allowing concurrent RCU readers to observe freed memory

## Requirements to Trigger

- **User namespaces**: Not required for the bug in general, but required for this exploit so an unprivileged user can create a network namespace and gain `CAP_NET_ADMIN` inside it.
- **Capabilities**: `CAP_NET_ADMIN` (inside the attacker's network namespace for this exploit)
- **Kernel configuration**: `CONFIG_NF_TABLES`, `CONFIG_NF_TABLES_INET`
- **Other**: Ability to saturate IPv6 hooks to `MAX_HOOK_COUNT` (1024) to force the IPv6 hook registration failure

## Commit Which Introduced the Vulnerability

- **Commit**: [`91c7b38dc9f0`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=91c7b38dc9f0de4f7f444b796d14476bc12df7bc) ("netfilter: nf_tables: use new transaction infrastructure to handle chain")
- This commit introduced the transaction-based chain handling and the vulnerable teardown path that removes a chain with `list_del_rcu()` and then frees it without waiting for an RCU grace period when hook registration fails.

## Commit Which Fixed the Vulnerability

- **Fix**: Add `synchronize_rcu()` between `nft_chain_del()` and `nf_tables_chain_destroy()` in the `err_register_hook` error path of `nf_tables_addchain()`.
- **Patch commit**: [`71e99ee20fc3`](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=71e99ee20fc3f662555118cf1159443250647533) ("netfilter: nf_tables: fix use-after-free in nf_tables_addchain()")

## Affected Kernel Versions

- **Introduced in**: 3.16 (when `91c7b38dc9f0` first shipped)
- **Affected stable ranges**: 3.16 - 6.1.164, 6.2 - 6.6.127, 6.7 - 6.12.74, 6.13 - 6.18.13, and 6.19 - 6.19.3
- **Fixed in**: 6.1.165, 6.6.128, 6.12.75, 6.18.14, 6.19.4, and mainline 7.0-rc1

## Blocking the Vulnerability

The vulnerability can be prevented by any of the following:

- **Disabling user namespaces** (`kernel.unprivileged_userns_clone=0` or equivalent) prevents this exploit path from obtaining `CAP_NET_ADMIN` in a private network namespace.
- **Blocking `NETLINK_NETFILTER` socket creation** from unprivileged contexts.
- **Disabling nf_tables support** (`CONFIG_NF_TABLES=n`) or, more narrowly, disabling INET chains (`CONFIG_NF_TABLES_INET=n`).
- **Limiting `nf_tables` access** via security modules (e.g., SELinux, AppArmor policies denying netfilter configuration).

## KASAN Report

```
BUG: KASAN: use-after-free in nft_do_chain+0x1214/0x12a0
Read of size 8 at addr ffff888103ef0b00 by task init/76
...
Allocated by task 77:
nf_tables_addchain.constprop.0+0x8f9/0x1f80
Freed by task 77:
nf_tables_chain_destroy+0xb8/0x530
nf_tables_addchain.constprop.0+0xe6f/0x1f80
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# kernelCTF exploit build for cos-113-18244.521.88
#
# Default target builds the kernelXDK-integrated version (exploit_xdk.cpp).
# Use 'make exploit_original' for the original C version (exploit.c).

KERNELXDK_INCLUDE_DIR ?=
KERNELXDK_LIB_DIR ?=

CXX ?= g++
CC ?= gcc
CXXFLAGS := -g -std=c++20 -I. -static -Os -ffunction-sections -fdata-sections -Wall -pthread
CFLAGS := -g -static -Os -ffunction-sections -fdata-sections -Wall -pthread -Wl,--gc-sections

ifneq ($(strip $(KERNELXDK_INCLUDE_DIR)),)
CXXFLAGS += -I$(KERNELXDK_INCLUDE_DIR)
endif

LDFLAGS := -Wl,--gc-sections -lkernelXDK -pthread
ifneq ($(strip $(KERNELXDK_LIB_DIR)),)
LDFLAGS := -L$(KERNELXDK_LIB_DIR) $(LDFLAGS)
endif

.PHONY: all prerequisites run clean

all: exploit

prerequisites: target_db.kxdb

# Download kernelXDK target database if not present
target_db.kxdb:
wget -q -O $@ https://storage.googleapis.com/kernelxdk/db/kernelctf.kxdb

# kernelXDK-integrated version (C++)
exploit: exploit_xdk.cpp target_db.kxdb
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS)
case "$@" in *debug*) ;; *) strip -s "$@" ;; esac

# Original C version (does not require kernelXDK)
exploit_original: exploit.c
$(CC) $(CFLAGS) -o $@ $<
case "$@" in *debug*) ;; *) strip -s "$@" ;; esac

run: exploit
./exploit

clean:
rm -f exploit exploit_original target_db.kxdb
Binary file not shown.
Loading
Loading