| # PoC β ExecuTorch delegate-loader OOB cluster (MPS + WebGPU runtime crashes + CoreML logic) |
|
|
| Two minimal, self-contained C++ programs that reproduce the vulnerable **logic** of `pytorch/executorch`'s CoreML in-memory-filesystem loader **verbatim**, so the memory-safety violation is reproducible in seconds with no ExecuTorch build. Both compile with stock `clang++` and standard headers only. **Updated 2026-07-14:** full `.pte`-triggered runtime crashes now also included for MPS and WebGPU backends. |
|
|
| ## What's here |
| | File | Demonstrates | Maps to (executorch @ main) | |
| |---|---|---| |
| | `craft_malformed_mps_pte.py` / `runtime_poc_mps.mm` / `malformed_mps.pte` / `RUNTIME_CRASH_REPORT.md` (runtime_mps_poc/) | **Runtime MPS PoC (2026-07-14):** generates a real `.pte` and crashes `MPSGraphBuilder.mm:162` via the actual `MPSGraph.framework` β OOB write at `_idToMPSGraphTensor[1000]` (vector size 3); heap corruption propagates to Metal/ARC cleanup (exit 137 SIGKILL on fresh build; exit 134 SEGV-in-`objc_release` on prior run β both captured in RUNTIME_CRASH_REPORT.md) | `backends/apple/mps/runtime/MPSGraphBuilder.mm:64,92,162` | |
| | `craft_malformed_webgpu_pte.py` / `runtime_poc_webgpu.cpp` / `malformed_webgpu.pte` / `RUNTIME_CRASH_REPORT.md` (runtime_webgpu_poc/) | **Runtime WebGPU PoC (2026-07-14):** generates a real `.pte` and crashes `WebGPUGraph.cpp:732-733` via attacker-controlled `cs.inline_offset` β same `vkgraph` schema Vulkan was patched for on 2026-05-13; WebGPU missed it (UBSan SEGV, `constant_data_ + 0xffffffffffff`, exit 134) | `backends/webgpu/runtime/WebGPUBackend.cpp:75`, `WebGPUGraph.cpp:378,537-538,732-733` | |
| | `poc_range_overflow_oob_read.cpp` | `Range::length() = offset + size` overflows `size_t` β wraps to a small value β bypasses `slice()`'s `length() > size()` guard β pointer returned past the buffer β OOB read | `backends/apple/coreml/runtime/inmemoryfs/range.hpp:20-21`, `memory_buffer.cpp:255` | |
| | `poc_oob_write.cpp` | `MemoryBuffer::write` does `memcpy(dst + offset, β¦)` with an attacker-controlled `offset` and no bounds check β out-of-bounds **write** β `SIGSEGV` | `backends/apple/coreml/runtime/inmemoryfs/memory_buffer.cpp:248-251` | |
| | `output.txt` | Captured run output (incl. the `SIGSEGV`/exit 139) | β | |
|
|
| The two structs/functions in each file are copied **verbatim** from the cited source so the crash maps 1:1 to the real code. |
|
|
| ## Build & run β CoreML logic PoCs (macOS/Linux, clang or gcc) |
| ```sh |
| # PoC 1 β overflow bypasses the bounds check, OOB read completes: |
| clang++ -std=c++17 -g -o p1 poc_range_overflow_oob_read.cpp && ./p1 |
| |
| # PoC 2 β controlled-offset OOB write crashes: |
| clang++ -std=c++17 -g -o p2 poc_oob_write.cpp && ./p2 ; echo "exit=$?" # 139 = SIGSEGV |
| ``` |
| For a sanitizer-confirmed report instead of a bare segfault, add `-fsanitize=address` (on macOS run with `ASAN_OPTIONS=symbolize=0` β the symbolizer can hang locally). |
|
|
| ## Build & run β Runtime MPS PoC (macOS only, Xcode CLT required) |
| ```sh |
| cd runtime_mps_poc |
| python3 craft_malformed_mps_pte.py # generates malformed_mps.pte |
| |
| clang++ -std=c++17 -fobjc-arc -g -fsanitize=undefined \ |
| -Ischemas \ |
| -framework Foundation -framework Metal \ |
| -framework MetalPerformanceShaders \ |
| -framework MetalPerformanceShadersGraph \ |
| runtime_poc_mps.mm -o poc_mps |
| |
| ./poc_mps malformed_mps.pte # exit 134 (UBSan SEGV in objc_release) or exit 137 (SIGKILL) |
| ``` |
|
|
| ## Build & run β Runtime WebGPU PoC (macOS/Linux, clang required) |
| ```sh |
| cd runtime_webgpu_poc |
| python3 craft_malformed_webgpu_pte.py # generates malformed_webgpu.pte |
| |
| # Requires flatbuffers headers β any install works, e.g. brew install flatbuffers |
| clang++ -std=c++17 -g -fsanitize=undefined \ |
| -I$(brew --prefix flatbuffers)/include \ |
| -Ischemas \ |
| runtime_poc_webgpu.cpp -o poc_webgpu |
| |
| ./poc_webgpu malformed_webgpu.pte # exit 134 (UBSan SEGV, constant_data_ + 0xffffffffffff) |
| ``` |
|
|
| ## Observed output β CoreML PoCs (see `output.txt`) |
| ``` |
| [*] length()=offset+size = 0 (wrapped past SIZE_MAX) |
| [*] guard 'length() > size()': 0 > 16 -> PASS (bypassed!) |
| [!] slice() returned ptr 20 bytes past a 16-byte buffer # PoC 1: OOB read |
| ... |
| [*] NO check that offset+size <= capacity; calling memcpy(dst+offset, ...) |
| exit=139 # PoC 2: SIGSEGV on the OOB write |
| ``` |
|
|
| ## Scope / honesty note |
| These reproduce the **vulnerable logic in isolation** β they prove the overflow bypass and the unchecked-offset write are real and crash. **Update (2026-07-14):** Full `.pte`-triggered runtime crashes for two additional backends are now included: the MPS backend (`runtime_mps_poc/`) crashes at `MPSGraphBuilder.mm:162` via `MPSGraph.framework` β OOB write at `_idToMPSGraphTensor[1000]`, heap corruption propagates to Metal/ARC cleanup (exit 137 SIGKILL on fresh build, exit 134 SEGV-in-`objc_release` on prior run); the WebGPU backend (`runtime_webgpu_poc/`) crashes at `WebGPUGraph.cpp:732-733` via the missing `flatbuffers::Verifier` β same `vkgraph` schema (`VK00`) Vulkan was patched for on 2026-05-13, WebGPU missed it (UBSan SEGV, `constant_data_ + 0xffffffffffff`, exit 134). No weaponized/code-execution exploit was written β the "code execution" impact in the main report is argued from primitive strength + precedent (CVE-2025-54950), not demonstrated. |
|
|
| `offset`/`size` in the real code are deserialized from the attacker-controlled in-memory-FS metadata inside a `.pte`; the harness feeds those exact values directly. |