# CVE-2026-35418 — Windows Cloud Files Mini Filter `cldflt.sys` Use-After-Free: Hydration-Slot Race Between Cleanup and Completion

---

## Summary

| | |
|---|---|
| **Product** | Windows — `cldflt.sys` (Cloud Files Mini Filter Driver; placeholder hydration) |
| **CVE ID** | CVE-2026-35418 |
| **Impact** | Elevation of Privilege |
| **MSRC severity** | Important |
| **CVSS** | 7.8 / 6.8 — `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-416 Use After Free; CWE-367 TOCTOU Race Condition |
| **Delivery** | Local race — trigger placeholder hydration while concurrently closing the same file handle |
| **KB / Fixed build** | KB5089549 — `cldflt.sys` 10.0.26100.8457 (Win11 24H2 x64) |
| **Patch Date** | May 12, 2026 (2026-May) |
| **Pre-patch binary** | `cldflt.sys` 10.0.26100.8328 — SHA256 `e190794e8e236f986e73f682f64b13d8ee5f044a7f8065765104471981016c6a` |
| **Post-patch binary** | `cldflt.sys` 10.0.26100.8457 — SHA256 `e818bc587f00e60ce73af8cfc98544b18a3763cb290bf85cb8548a498446f2c2` |
| **Feature flag** | `Feature_955245880` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation Less Likely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`cldflt.sys` is the Windows **Cloud Files mini filter driver** backing
OneDrive-style placeholder files. When a cloud-synced placeholder is accessed it
is **hydrated** (its data fetched). The driver tracks the active hydration
context for a stream in a pointer slot at **`StreamHandleContext + 0x38`**. The
driver runs in kernel and the paths are reachable by a local user, so a
lifetime bug in that slot is a local elevation vector.

---

## Vulnerability Summary

Two paths share the slot at `StreamHandleContext + 0x38`:

- **`HsmiRecallPostProcessHydration`** (completion) inserts the hydration entry
  atomically only when the slot is empty: `InterlockedCompareExchange64(slot,
  Entry, 0)`.
- **`HsmFltPreCLEANUP`** (handle close), via the terminate-hydration helper,
  cancels an in-progress hydration.

Pre-patch the cleanup path used a **destructive** `InterlockedExchange64(slot,
0)` — it unconditionally set the slot to `0` and returned the old value:

```c
// terminate-hydration path (10.0.26100.8328) — PRE-PATCH, from our diff
LOCK(); uVar1 = *(u64*)(param_1 + 0x38); *(u64*)(param_1 + 0x38) = 0; UNLOCK();  // slot := 0
// ... then begins releasing the file handle / freeing resources ...
```

That creates a race window: immediately after cleanup zeroes the slot, a
hydration completion callback on another CPU runs `CompareExchange64(slot, Entry,
0)`, finds `0`, and **succeeds** — inserting a fresh hydration entry. But cleanup
has already started freeing the handle, so the hydration path then operates on a
freed/invalid resource — a **use-after-free** (CWE-416 / CWE-367). It triggers
when one thread hydrates a cloud placeholder while another closes the same
handle.

---

## Prerequisites and Constraints

- Local, low-privileged (`PR:L`, `AV:L`, `AC:L`).
- Race: concurrently trigger hydration of a cloud-synced placeholder and close
  the same file handle so the completion callback and cleanup overlap on the
  shared `+0x38` slot.

---

## Vulnerability Details

### Root Cause

Cleanup's destructive `InterlockedExchange64(slot, 0)` leaves the slot in the
exact state (`0`) that the completion path's CAS-insert treats as "empty and
insertable", so a new hydration entry can be installed after cleanup has begun
tearing down the handle — the two paths act on the same object across a free.

### The patch (confirmed — diff, .8328 → .8457)

Gated behind `Feature_955245880`, the cleanup/terminate path stops clearing the
slot to `0` and instead **marks bit 0** of the existing pointer with a
CAS loop:

```c
// terminate-hydration path (10.0.26100.8457) — PATCHED, feature-enabled branch
if (Feature_955245880__private_IsEnabledDeviceUsageNoInline() == 0) {
    LOCK(); uVar1 = *(u64*)(param_1+0x38); *(u64*)(param_1+0x38) = 0; UNLOCK();   // old destructive path
}
else {
    LOCK(); uVar1 = *(u64*)(param_1+0x38); if (uVar1==0){*(u64*)(param_1+0x38)=0;uVar1=0;} UNLOCK();
    do {
        param_2 = uVar1;
        if ((param_2 & 1) != 0) return;                 // *** bit 0 already set -> skip (LABEL_77) ***
        LOCK();
        uVar1 = *(u64*)(param_1+0x38);
        if (param_2 == uVar1) *(u64*)(param_1+0x38) = param_2 | 1;   // *** CAS: slot = ptr | 1 ***
        UNLOCK();
    } while (uVar1 != param_2);
}
```

Because kernel pool allocations are ≥ 8-byte aligned, bits 0–2 of a valid pointer
are always `0`, so `ptr | 1` is a **sentinel** distinguishable from a real pointer
and can never be `0`. After cleanup marks the slot, the completion path's
`CompareExchange64(slot, Entry, 0)` can **no longer succeed** (the slot is not
`0`), closing the race. The CAS loop's bit-0 test also makes concurrent cleanup
threads safe (a second cleanup sees bit 0 set and takes the skip path). The old
`0x800` synchronization flag is now set only on the feature-disabled path
(`if (feature==0) *(u32*)(entry+0x30) |= 0x800;`) — the bit-0 protocol supersedes
it when the feature is enabled.

### Patch Completeness Assessment

**CFR-gated behind `Feature_955245880`.** The bit-0 marking runs only when the
flag is enabled; the original destructive `InterlockedExchange64(slot, 0)` path
still ships in .8457. Patch state is not determined by file version alone — the
runtime-gated pattern seen across this corpus. Verify `Feature_955245880` is
enabled to confirm the race-free path is live.

---

## Detection Guidance

**Behavioural.** Concurrent hydration-trigger and handle-close on the same
cloud placeholder; interleaved `cldflt` hydration-completion and cleanup activity
on one stream.

**Crash signature.** Kernel UAF / pool-corruption bugchecks in
`cldflt!HsmiRecallPostProcessHydration` / `HsmFltPreCLEANUP` /
`HsmpRecallTerminateProgressiveHydration` under placeholder hydration + close.

**Config.** The fix is CFR-gated — confirm `Feature_955245880` is enabled so the
bit-0 marking protocol is active.

---

## References

- MSRC advisory — CVE-2026-35418 (Windows Cloud Files Mini Filter Driver Elevation of Privilege), released 2026-05-12, KB5089549.
- Full binary diff: `/data/patch_diffs/cldflt_sys-cve-2026-35418-ghidriff.md`
