# clfs.sys Patch Diff — CVE-2026-40407

| | |
|---|---|
| Binary | clfs.sys (Windows Common Log File System Driver) |
| Pre-patch version | 10.0.28000.1896 |
| Post-patch version | 10.0.28000.2113 |
| KB | KB5089549 |
| CVE | CVE-2026-40407 — Heap-based buffer overflow, Elevation of Privilege |
| Diff tool | ghidriff (Ghidra VersionTrackingDiff engine) |
| Functions changed | 1 (code change) |
| Functions added | 0 |

## Attribution note

This diff job (`clfs-2026-04.sys` vs `clfs-2026-05.sys`) covers the same May
2026 CLFS patch as CVE-2026-40397 (CWE-191, integer underflow). Two new
feature flags appear in the post-patch binary, each gating a different kind
of added validation. The function below contains the flag whose check
matches CVE-40407's CWE (a bounds check guarding a buffer copy, i.e.
heap-overflow shaped); the other flag, in `AdjustReservation`, is covered on
CVE-2026-40397's page instead. **This attribution is inferred from the
semantics of each check, not confirmed against Microsoft's internal change
records** — treat it as well-reasoned static analysis, not ground truth.

## Summary

CVE-2026-40407 is a heap-based buffer overflow fix in
`CClfsLogFcbPhysical::ReadLogBlock`. The patch adds a new staged-rollout
flag, `Feature_748929339`, and gates a bounds check behind it: after
resolving the next owner-page LSN, the patched code now checks whether the
caller-supplied LSN (`param_2`) is within that boundary *before* falling
through into the block-copy loop that calls `CcCopyRead`/`memset` against
the read buffer. Pre-patch, there was no such check at this point — an
out-of-range LSN could drive the subsequent copy past the buffer's expected
extent. Because the fix is feature-flagged, it is currently inert wherever
Microsoft hasn't yet flipped `Feature_748929339` on for that cohort.

## Functions changed

### CClfsLogFcbPhysical::ReadLogBlock

| | |
|---|---|
| Address | 140002470 |
| Change type | code, length, name, sig, calling, called |
| Patch flag added | **Yes** — `Feature_748929339__private_IsEnabledDeviceUsageNoInline` |

The pre-patch binary's symbols were unresolved for this function
(`FUN_140002470`); the post-patch binary resolves it as
`ReadLogBlock`. Most of the textual diff is symbol-resolution noise from
that — the actual security-relevant change is the new flag-gated bounds
check inserted right before the read-buffer copy loop:

```c
    cVar5 = (**(code **)(*(longlong *)this + 0x138))(this);
    if (cVar5 != '\0') {
      plVar11 = (longlong *)GetNextOwnerPageLsn(this,(_CLS_LSN *)&local_c0,(ulong)param_2);
      lVar17 = *plVar11;
      local_f8 = lVar17;
//  >>> patch flag check added here <<<
      uVar12 = Feature_748929339__private_IsEnabledDeviceUsageNoInline();
      if ((int)uVar12 != 0) {
        if (param_2 == (_CLS_LSN *)0x0) {
          bVar1 = false;
LAB_2:
          if (bVar1) goto LAB_3;
        }
        else if ((*(uint *)(param_2 + 4) <= local_f8._4_4_) &&
                ((local_f8._4_4_ != *(uint *)(param_2 + 4) || (*(uint *)param_2 < (uint)lVar17))) {
          bVar1 = true;
          goto LAB_2;
        }
//  >>> bail out instead of falling into the copy loop below <<<
        pIVar20 = (IClfsRequestAsync *)&DAT_4;
        goto LAB_0;
      }
    }
LAB_3:
    /* ... falls through into the CcCopyRead/memset block-copy loop ... */
```

The check compares the caller-supplied LSN against the owner-page boundary
(`local_f8`) just resolved above, and bails out (`&DAT_4`, jump to `LAB_0`)
when it's out of range — before any of the loop below (`memset`, `CcCopyRead`
against `local_d8`, the read buffer) executes. Without this gate, an
out-of-range LSN reaches the copy loop and can drive a write past the
buffer's validated extent — a heap-based buffer overflow.

---

<sub>Source: ghidriff diff of clfs-2026-04.sys (10.0.28000.1896, pre-patch) vs clfs-2026-05.sys (10.0.28000.2113, post-patch) — [download pre](/data/patch_diffs/binaries/clfs-2026-04.sys) / [download post](/data/patch_diffs/binaries/clfs-2026-05.sys). This report covers only the function attributed to CVE-2026-40407; the same diff job also covers CVE-2026-40397 (see that CVE's own report). Raw ghidriff output (full metadata, decompiler options, mermaid charts) is preserved in diffing/2026-05/clfs-kb5089549/json/clfs-2026-04.sys-clfs-2026-05.sys.ghidriff.json.</sub>
