# RCA — CVE-2025-21372 (bfs.sys named-pipe mapping UAF race)

- **Binary:** `bfs.sys` (Brokering File System minifilter)
- **Patch:** KB5050009 (Jan 2025), `10.0.26100.2454` → `10.0.26100.2894`
- **Class:** CWE-416 use-after-free (race) | **Impact:** EoP | **ITW:** no
- **Primary source:** [HT3Labs](https://ht3labs.com/Brokering-File-System-January-2025-Patch-Analysis.html)
- **Diff:** `ghidriff/CVE-2025-21315/output/bfs-10.0.26100.2454.sys-bfs-10.0.26100.2894.sys.ghidriff.md` (shared with CVE-2025-21315)

## Root cause

`BfsReleaseNamedPipeMapping()` decrements `PipeEntry->RefCt` **before** acquiring
the `PipeMappingTable` pushlock:

```c
if ( _InterlockedExchangeAdd(&PipeEntry->RefCt, -1) == 1 )   // dec first
{
    ExAcquirePushLockExclusiveEx(PipeMappingTable, 0);        // lock second (too late)
    if ( !PipeEntry->RefCt ) { ...free PipeEntry... }
    ExReleasePushLockExclusiveEx(...);
}
```

Race with two threads holding the same named-pipe mapping (RefCt = 2):

1. Thread A decrements RefCt 2→1, then waits on the lock.
2. Thread B decrements RefCt 1→0, acquires the lock, frees `PipeEntry`, unlocks.
3. Thread A acquires the lock and evaluates `if (!PipeEntry->RefCt)` on freed
   memory → UAF read; a reclaimed entry turns this into type confusion.

## Patch

Gated by `Feature_752421176`: the `PipeMappingTable` pushlock is taken at function
entry (before the refcount decrement) and held for the whole release path.
The gate is referenced **only** in `BfsReleaseNamedPipeMapping` — a clean
attribution anchor. Confirmed in the ghidriff diff:

- Added: `Feature_752421176__private_IsEnabledDeviceUsageNoInline`, `..._IsEnabledFallback`
- Modified: `BfsReleaseNamedPipeMapping` (72% match)

## Reaching the bug

Named-pipe operations brokered by BFS from an AppContainer/AppSilo process:
open two handles to the same named pipe under BFS management and race
close/release on two threads. No IOCTL needed — the minifilter intercepts the
pipe I/O path. Objects: `PipeMappingTable { PushLock, RTL_DYNAMIC_HASH_TABLE }`,
`PipeEntry { HashEntry, RefCt, UserSid, AppContainerSid, FilePath, ... }`.

## Detection notes

- Race-window bug: look for processes under AppContainer spawning threads that
  hammer duplicate named-pipe create/close.
- Crash signature: access violation in `bfs!BfsReleaseNamedPipeMapping`.
- Same-month sibling: CVE-2025-21315 (PolicyTable locking) — see
  `rca-cve-2025-21315.md`.
