NVIDIA Driver - Incorrect Bounds Check in Escape 0x70001b2







Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=940

The DxgkDdiEscape handler for 0x70001b2 doesn't do proper bounds checks for its
variable size input.

void sub_8C4304(...) {
        // escape_->size is controlled by the user.
        if ( escape_->size < size )
          size = escape_->size;
        memcpy(escape_->data, v31, 28i64 * size);

Note that this appears to be a common pattern. Normally, before
escape handlers are executed, |PrivateDriverDataSize| (from DXGKARG_ESCAPE)
is checked to be equal to some value against a hardcoded table. However, some escapes
allow a more relaxed check that |PrivateDriverDataSize| >= minimum. This means that
the handler themselves must implement an ad hoc bounds check, which either seems to be
missing or implemented incorrectly (relying on a user specified value) in many cases.

bug 936 is a similar issue and there are likely more. I've noticed (but not confirmed)
a few more OOB reads that I haven't reported that follow this same pattern.

Crashing context with PoC (Win 10 x64 with 372.54):

Invalid system memory was referenced.  This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
rax=ffffd000239d51dc rbx=0000000000000000 rcx=fffffffffffffff4
rdx=fffff000e9e6c754 rsi=0000000000000000 rdi=0000000000000000
rip=fffff80166d6aca0 rsp=ffffd000239d3df8 rbp=ffffd000239d3f00
 r8=0000000000000924  r9=000000000000003b r10=000000000000e9ef
r11=ffffd000239d48ac r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei ng nz ac pe cy
fffff801`66d6aca0 f30f7f40f0      movdqu  xmmword ptr [rax-10h],xmm0 ds:ffffd000`239d51cc=????????????????????????????????
Resetting default scope

To reproduce, compile as an x64 executable an run (requires WDK for D3DKMTEscape).

Proof of Concept: