CVE-2026-20820 — CLFS ScanContainers Integer Overflow (IOCTL 0x80076816)
Last updated: 2026-04-10
Component: clfs.sys
Bug Class: Integer overflow → OOB write
Status: Patched (2026)
Exploited ITW: Unknown
Related: Clfs, Integer Overflows
Tags:clfs,integer-overflow,ioctl,oob-write,kernel-mode,lpe,scancontainers
Summary
CVE-2026-20820 is an integer overflow in CClfsRequest::ScanContainers, triggered via IOCTL 0x80076816 (METHOD_OUT_DIRECT). The vulnerability: the output buffer size calculation multiplies ContainerCount * sizeof(CLS_CONTAINER_INFORMATION) (0x240 bytes each) but does NOT account for the 0x38-byte CLS_SCAN_CONTEXT header that also resides in the same output buffer. This allows the last CLS_CONTAINER_INFORMATION structure to be written 0x38 bytes past the end of the allocated output buffer — an OOB write of up to 0x240 bytes with partially controlled data.
IOCTL Details
IOCTL Code: 0x80076816
Direction: METHOD_OUT_DIRECT
Input buffer: ContainerCount (ULONG), scan context parameters
Output buffer: [CLS_SCAN_CONTEXT (0x38 bytes)] [CLS_CONTAINER_INFORMATION[N] (0x240 bytes each)]
Vulnerable Code Path
// CClfsRequest::ScanContainers:
// User-supplied ContainerCount from IOCTL input
// Calculated buffer requirement:
output_size = ContainerCount * sizeof(CLS_CONTAINER_INFORMATION); // 0x240 * N
// BUT: the output buffer also contains a CLS_SCAN_CONTEXT header (0x38 bytes):
// Actual buffer layout: [0x38-byte header][0x240-byte entry #0][...][0x240-byte entry #N-1]
//
// No check: output_size + 0x38 <= MDL_output_buffer_length ?
//
// When writing entry #N-1:
write_address = output_buffer + 0x38 + (N-1) * 0x240;
// If ContainerCount is crafted such that:
// (ContainerCount-1) * 0x240 + 0x38 > MDL_buffer_size
// → writes 0x240 bytes past the end of the output MDL mapping
CLS_SCAN_CONTEXT Structure (0x38 bytes)
typedef struct _CLS_SCAN_CONTEXT {
CLFS_NODE_ID cidNode; // +0x00: type + size
HANDLE hLog; // +0x08: log file handle
ULONG cIndex; // +0x10: current scan position
ULONG cContainers; // +0x14: containers per scan
ULONG cContainersReturned; // +0x18
CLS_LOG_INFORMATION_CLASS eInformation; // +0x1C
CLS_CONTAINER_INFORMATION pinfoContainer; // +0x20: starts at +0x20, size 0x18?
// ...total 0x38 bytes
} CLS_SCAN_CONTEXT, *PCLS_SCAN_CONTEXT;
CLS_CONTAINER_INFORMATION Structure (0x240 bytes)
typedef struct _CLS_CONTAINER_INFORMATION {
ULONG FileAttributes; // +0x000
ULONGLONG CreationTime; // +0x008
ULONGLONG LastAccessTime; // +0x010
ULONGLONG LastWriteTime; // +0x018
LONGLONG ContainerSize; // +0x020
ULONG FileNameActualLength; // +0x028
ULONG FileNameLength; // +0x02C
WCHAR FileName[ANYSIZE_ARRAY]; // +0x030: up to 0x210 bytes
CLFS_CONTAINER_STATE State; // overlaps FileName tail region
ULONG PhysicalContainerId;
ULONG LogicalContainerId;
// ...total 0x240 bytes
} CLS_CONTAINER_INFORMATION, *PCLS_CONTAINER_INFORMATION;
The overflow writes: container State flags + PhysicalContainerId + LogicalContainerId + FileName tail (attacker-controlled container file names) — partially controlled OOB write data.
Exploitation Approach
OOB Write Target
The output MDL maps to a kernel buffer. The OOB write lands at (MDL_mapped_va + MDL_size) — the next kernel pool allocation after the output buffer.
Grooming: Create output buffers of known size. The adjacent pool allocation can be a target object (pipe attribute, registry value buffer, etc.) whose fields overlap with the OOB write offset.
Controlled Data in OOB Region
The FileName field of CLS_CONTAINER_INFORMATION is populated from actual container file names. By creating containers with carefully crafted names, the attacker partially controls what data is written OOB. Specifically:
State(ULONG): container state flags — not fully controlledPhysicalContainerId/LogicalContainerId(ULONGs): container IDs — sequential, predictableFileNametail: WCHAR string from attacker-named container file — controlled up to ~0x200 bytes
Affected API
// User-mode trigger:
BOOL CreateLogContainerScanContext(
HANDLE hLog,
ULONG cFromContainer,
ULONG cContainers, // ← ContainerCount — attacker controls
CLS_LOG_INFORMATION_CLASS eInformation,
PCLS_SCAN_CONTEXT pScanContext,
LPOVERLAPPED pOverlapped
);
// Then: ScanLogContainers() issues IOCTL 0x80076816 with ContainerCount in input
Notes
- Requires medium integrity (any standard user account)
- No special kernel object or prior info leak required to trigger the OOB
- Partially controlled data limits exploitation compared to fully controlled OOB writes
- Full exploit PoC not publicly available as of 2026-04-10
References
- CVE-2026-20820 root cause analysis (raw_sources in this knowledge base)
- Microsoft MSRC — CVE-2026-20820 advisory
