# cldflt.sys Patch Diff — CVE-2026-58613

| | |
|---|---|
| Binary | cldflt.sys (Cloud Files Mini Filter Driver) |
| Pre-patch version | 10.0.26100.8737 |
| Post-patch version | 10.0.26100.8875 |
| KB | KB5101650 |
| CVE | CVE-2026-58613 — Use After Free (CWE-416), Elevation of Privilege, CVSS 8.8 |
| Diff tool | ghidriff (Ghidra VersionTrackingDiff engine) |
| Functions changed | 3 with code changes (out of 2,848 total) |
| Functions added | 0 |

## Summary

The fix corrects a **use-after-free** in `CldiStreamCompleteRequest` caused by
an inverted deletion order introduced under `Feature_2089223483` in the May 2026
update.

When the feature flag is enabled, the pre-patch code calls
`CldiStreamDeleteRequest` (which releases the stream context reference via
`FltReleaseContext`) **before** `CldiStreamCdqRELEASE`. If the orphaned
timer-list request holds the last reference to the stream context, the pool
block is freed by `CldiStreamDeleteRequest`, and the subsequent
`CldiStreamCdqRELEASE` dereferences a dangling pointer — a classic UAF.

The patch swaps the call order back to the correct sequence (release CDQ first,
then delete request) and adds an explicit `CdqACQUIRE` reference hold in
`CldiStreamCompleteCanceledRequest` to ensure the stream context survives
through the completion sequence.

### Vulnerable decompilation (pre-patch, Ghidra-verified)

`CldiStreamCompleteRequest @ 0x1400841bc`:

```c
void CldiStreamCompleteRequest(
    longlong *pStreamHandleCtx,   // param_1
    uint     *pRequest,           // param_2
    ulonglong completionStatus,   // param_3
    uint      cancelFlags)        // param_4
{
    // ... WPP tracing, request-list manipulation ...

    uVar5 = Feature_2089223483__private_IsEnabledDeviceUsageNoInline();

    if ((int)uVar5 == 0) {
        // OLD PATH — correct order:
        if (*(char *)((longlong)pRequest + 0x69) == '\0') {
            CldiStreamCdqRELEASE(
                *(longlong *)(*pStreamHandleCtx + 8) + 0x90);  // RELEASE first
        }
        CldiStreamDeleteRequest(pRequest);                       // then DELETE
    }
    else {
        // NEW PATH (Feature_2089223483 enabled) — VULNERABLE:
        CldiStreamDeleteRequest(pRequest);                       // DELETE first ← FREE
        CldiStreamCdqRELEASE(
            *(longlong *)(*pStreamHandleCtx + 8) + 0x90);       // ← UAF!
    }
}
```

### The fix (post-patch)

The `else` branch is corrected to match the `if` branch's ordering — CDQ
release runs before the delete:

```c
    else {
        // FIXED: correct order restored
        if (*(char *)((longlong)pRequest + 0x69) == '\0') {
            CldiStreamCdqRELEASE(
                *(longlong *)(*pStreamHandleCtx + 8) + 0x90);  // RELEASE first
        }
        CldiStreamDeleteRequest(pRequest);                       // then DELETE
    }
```

### Trigger path

```
User-mode:
  CfRegisterSyncRoot + CfConnectSyncRoot
    → Create placeholder file
    → CfReportProviderProgress2(completed < total)
      → request inserted onto global timer list (60s deadline)
    → Provider process exits WITHOUT CfDisconnectSyncRoot
      → request orphaned on timer list

  ~60 seconds later, or forced via CfQueryProgress(port cmd 0x4001):
    → CldiStreamStartCountdownTimer walks expired entries
      → CldiStreamCancelSynchronousRequest
        → CldiStreamCompleteCanceledRequest
          → CldiStreamCompleteRequest  ← UAF here
```

## Functions changed

### CldiStreamCompleteRequest

| | |
|---|---|
| Address | 1400841bc |
| Change type | code, length, called |
| Similarity | 0.85 |
| Fix | Swap deletion order under `Feature_2089223483` — CDQ release before delete |

The `else` branch (feature flag enabled) had `CldiStreamDeleteRequest` before
`CldiStreamCdqRELEASE`. The fix swaps them back to the safe order. When the
orphaned request holds the last stream context reference, the old order freed
the pool block before the CDQ release tried to dereference it.

### CldiStreamCompleteCanceledRequest

| | |
|---|---|
| Address | 140040c58 |
| Change type | code, called |
| Similarity | 0.92 |
| Fix | Added `CdqACQUIRE` reference hold before calling `CompleteRequest` |

New call to `CldiStreamCdqACQUIRE` when `Feature_2089223483` is enabled,
ensuring the stream context refcount is bumped before entering the completion
path. This is a belt-and-suspenders fix alongside the reordering.

### CldiStreamCancelSynchronousRequest

| | |
|---|---|
| Address | 1400409f8 |
| Change type | code, called |
| Similarity | 0.90 |
| Fix | Added `CldiCanDoNonCdqCompletion` check under feature flag |

New guard check before entering the cancellation path when the feature flag is
enabled. Prevents the completion from proceeding if the CDQ state is
inconsistent.

---

<sub>Source: ghidriff diff of cldflt-2026-06.sys (10.0.26100.8737, pre-patch)
vs cldflt-2026-07.sys (10.0.26100.8875, post-patch) —
[download pre](/data/patch_diffs/binaries/cldflt-2026-06.sys) /
[download post](/data/patch_diffs/binaries/cldflt-2026-07.sys).</sub>
