Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
634 changes: 634 additions & 0 deletions pocs/linux/kernelctf/CVE-2026-23278_cos/docs/exploit.md

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions pocs/linux/kernelctf/CVE-2026-23278_cos/docs/vulnerability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Vulnerability

A use-after-free vulnerability was found in the Linux kernel's Netfilter nf_tables subsystem (`net/netfilter/nf_tables_api.c`). A `break` statement in both `nft_map_catchall_deactivate()` and `nft_map_catchall_activate()` causes incomplete processing when two catchall elements coexist in a verdict map during the same transaction. When the set is also being deleted in the same batch, the `break` causes the second catchall element's chain reference to be mismanaged during the abort path, leading to a `chain->use` counter underflow to zero and a subsequent use-after-free of the `nft_chain` object. This leads to local privilege escalation (LPE).

## Requirements to trigger the vulnerability:
- Capabilities: To trigger the vulnerability, `CAP_NET_ADMIN` capability is required to access the Netfilter system.
- Kernel configuration: Kernel configs related to the Netfilter nf_tables system (e.g., `CONFIG_NETFILTER`, `CONFIG_NF_TABLES`) are required to trigger this vulnerability. This config is generally enabled by default (ex. x86_64_defconfig).
- Are user namespaces needed?: Yes. As this vulnerability requires `CAP_NET_ADMIN`, which is not usually given to the normal user, we used the unprivileged user namespace to achieve this capability.

## Commit which introduced the vulnerability
- This vulnerability was introduced in Linux v6.4, with commit [628bd3e49cba1c066228e23d71a852c23e26da73](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=628bd3e49cba1c066228e23d71a852c23e26da73)
- This commit ("netfilter: nf_tables: drop map element references from preparation phase") restructured the handling of map element data references such that a pending `DELSETELEM` and a `NEWSETELEM` in the same batch can both leave catchall elements in the set's `catchall_list` simultaneously, exposing the latent `break`-statement bug in `nft_map_catchall_deactivate()` and `nft_map_catchall_activate()`.

## Commit which fixed the vulnerability
- This vulnerability was fixed with commit [7cb9a23d7ae40a702577d3d8bacb7026f04ac2a9](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7cb9a23d7ae40a702577d3d8bacb7026f04ac2a9) ("netfilter: nf_tables: always walk all pending catchall elements"), which removes the `break` statements from both `nft_map_catchall_deactivate()` and `nft_map_catchall_activate()` so that all catchall elements are processed — not just the first matching one — when a verdict map containing multiple pending catchalls is toggled during a transaction.

## Affected kernel versions
- Linux versions containing commit 628bd3e49cba and lacking the fix ("netfilter: nf_tables: always walk all pending catchall elements") are affected.

## Affected component, subsystem
- net/netfilter (nf_tables)

## Cause (UAF, BoF, race condition, double free, refcount overflow, etc)
- Use-after-free (`chain->use` counter underflow to zero via incomplete catchall processing → premature `kfree` of `nft_chain`)

## Which syscalls or syscall parameters are needed to be blocked to prevent triggering the vulnerability? (If there is any easy way to block it.)
- Disable syscalls for Netfilter (specifically, Netfilter nf_tables) system (ex. `socket`, `sendmsg` with Netlink socket) to prevent this vulnerability.
- Disable syscalls for unprivileged user namespace (ex. `clone`, `unshare`) can reduce the attack surface since the Netfilter system requires `CAP_NET_ADMIN` to use.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
CC = g++
SRCS := ./exploit.cpp
TARGET := exploit
LIBMNL_DIR = $(realpath ./)/libmnl_build
LIBNFTNL_DIR = $(realpath ./)/libnftnl_build
LIBXDK_DIR = $(realpath ./)/libxdk_build

CFLAGS = -w -static -Wall -fpermissive
LIBS = -L$(LIBMNL_DIR)/install/usr/local/lib -L$(LIBNFTNL_DIR)/install/usr/local/lib -L$(LIBXDK_DIR)/lib -lnftnl -lmnl -lkernelXDK -lkeyutils
INCLUDES = -I$(LIBMNL_DIR)/install/usr/local/include -I$(LIBNFTNL_DIR)/install/usr/local/include -I$(LIBXDK_DIR)/include

$(TARGET) : libmnl-build libnftnl-build libxdk-build target_db.kxdb
$(CC) $(CFLAGS) $(SRCS) -o $(TARGET) $(INCLUDES) $(LIBS)

libmnl-build : libmnl-download
tar -C $(LIBMNL_DIR) -xvf $(LIBMNL_DIR)/libmnl-1.0.5.tar.bz2
cd $(LIBMNL_DIR)/libmnl-1.0.5 && ./configure --enable-static
cd $(LIBMNL_DIR)/libmnl-1.0.5 && make -j`nproc`
cd $(LIBMNL_DIR)/libmnl-1.0.5 && mkdir ../install && make DESTDIR=`realpath ../install` install

libnftnl-build : libmnl-build libnftnl-download
tar -C $(LIBNFTNL_DIR) -xvf $(LIBNFTNL_DIR)/libnftnl-1.2.1.tar.bz2
cd $(LIBNFTNL_DIR)/libnftnl-1.2.1 && PKG_CONFIG_PATH=$(LIBMNL_DIR)/install/usr/local/lib/pkgconfig ./configure --enable-static
cd $(LIBNFTNL_DIR)/libnftnl-1.2.1 && C_INCLUDE_PATH=$(C_INCLUDE_PATH):$(LIBMNL_DIR)/install/usr/local/include LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(LIBMNL_DIR)/install/usr/local/lib make -j`nproc`
cd $(LIBNFTNL_DIR)/libnftnl-1.2.1 && mkdir ../install && make DESTDIR=`realpath ../install` install

libmnl-download :
mkdir $(LIBMNL_DIR)
wget -P $(LIBMNL_DIR) https://netfilter.org/projects/libmnl/files/libmnl-1.0.5.tar.bz2

libnftnl-download :
mkdir $(LIBNFTNL_DIR)
wget -P $(LIBNFTNL_DIR) https://netfilter.org/projects/libnftnl/files/libnftnl-1.2.1.tar.bz2

libxdk-build :
mkdir -p $(LIBXDK_DIR)
wget -O $(LIBXDK_DIR)/libxdk-v0.1.tar.gz https://github.com/google/kernel-research/releases/download/libxdk/v0.1/libxdk-v0.1.tar.gz
tar -C $(LIBXDK_DIR) -xzf $(LIBXDK_DIR)/libxdk-v0.1.tar.gz

target_db.kxdb :
wget -O target_db.kxdb https://storage.googleapis.com/kernelxdk/db/kernelctf.kxdb

exploit_debug : libmnl-build libnftnl-build libxdk-build target_db.kxdb
$(CC) $(CFLAGS) $(SRCS) -o exploit_debug $(INCLUDES) $(LIBS)

.PHONY: libmnl-build libnftnl-build libxdk-build libmnl-download libnftnl-download clean exploit_debug

clean:
rm -f $(TARGET) exploit_debug
if [ -d $(LIBMNL_DIR)/libmnl-1.0.5 ]; then cd $(LIBMNL_DIR)/libmnl-1.0.5 && make DESTDIR=`realpath ../install` uninstall; fi
if [ -d $(LIBNFTNL_DIR)/libnftnl-1.2.1 ]; then cd $(LIBNFTNL_DIR)/libnftnl-1.2.1 && make DESTDIR=`realpath ../install` uninstall; fi
rm -rf $(LIBMNL_DIR)
rm -rf $(LIBNFTNL_DIR)
rm -rf $(LIBXDK_DIR)
rm -f target_db.kxdb
Binary file not shown.
Loading
Loading