| # executorch FlatTensorDataMap .ptd null-pointer dereference (CWE-476) |
|
|
| Null-pointer dereference in the ExecuTorch `.ptd` (FlatTensor named-data map) |
| loader. A crafted `.ptd` whose `TensorLayout` omits the non-required flatbuffer |
| fields `sizes` and/or `dim_order` drives `create_tensor_layout()` to dereference |
| a `nullptr` accessor result, crashing any process that loads the file. |
|
|
| - Target: `pytorch/executorch` |
| - Commit: `9b7fd14a91fb5222f6da83be7dcdb72af2710530` |
| - Vulnerable file: `extension/flat_tensor/flat_tensor_data_map.cpp` |
| - Vulnerable function: `create_tensor_layout()` (lines 114-125) |
| - Reached via public API: `FlatTensorDataMap::get_tensor_layout()` (line 143) |
| - Schema: `extension/flat_tensor/serialize/flat_tensor.fbs` |
|
|
| ## Files |
|
|
| - `poc_flat_tensor.cpp` - harness. Builds a malicious `.ptd` (FlatTensor with |
| a `NamedData` whose `TensorLayout` omits `sizes` or `dim_order`), then drives |
| the REAL `FlatTensorDataMap::load()` + `get_tensor_layout("weight")`. |
| - `malicious_sizes.ptd` - crafted `.ptd` with `TensorLayout.sizes` omitted. |
| Crashes at `flat_tensor_data_map.cpp:118` (`sizes()->size()`). |
| - `malicious_dimorder.ptd` - crafted `.ptd` with `TensorLayout.dim_order` |
| omitted. Crashes at line 124 (null `dim_order` Span consumed by |
| `TensorLayout::create`). |
| - `asan_sizes.txt`, `asan_dimorder.txt` - captured ASan SEGV output. |
|
|
| ## Build |
|
|
| Against a standard ExecuTorch ASan build |
| (`-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON`, |
| `CMAKE_CXX_FLAGS="-fsanitize=address -g -O0 -fno-omit-frame-pointer"`): |
|
|
| ``` |
| clang++ -g -O0 -fsanitize=address -fno-omit-frame-pointer -std=c++17 \ |
| -I<build>/extension/flat_tensor/include -I<build>/include \ |
| -I<src>/.. -I<src>/runtime/core/portable_type/c10 \ |
| -I<src>/third-party/flatbuffers/include \ |
| poc_flat_tensor.cpp \ |
| <build>/extension/flat_tensor/libextension_flat_tensor.a \ |
| <build>/extension/data_loader/libextension_data_loader.a \ |
| <build>/libexecutorch_core.a <build>/libexecutorch.a \ |
| -o poc |
| ``` |
|
|
| ## Run |
|
|
| ``` |
| ./poc malicious_sizes.ptd sizes # omit sizes -> SEGV at line 118 |
| ./poc malicious_dimorder.ptd dim_order # omit dim_order -> SEGV at line 124 |
| ``` |
|
|
| The malicious `.ptd` files are also provided pre-built and can be loaded by any |
| application that consumes untrusted `.ptd` external-data files via |
| `FlatTensorDataMap`. |
|
|
| ## Root cause |
|
|
| `extension/flat_tensor/serialize/flat_tensor.fbs`: |
|
|
| ``` |
| table TensorLayout { |
| scalar_type: executorch_flatbuffer.ScalarType; |
| sizes: [int32]; // NON-required (optional) |
| dim_order: [uint8]; // NON-required (optional) |
| } |
| ``` |
|
|
| `sizes` and `dim_order` are optional, so the FlatBuffers accessors |
| `tensor_layout->sizes()` and `tensor_layout->dim_order()` return `nullptr` when |
| the fields are omitted. `create_tensor_layout()` dereferences them with no null |
| check. |
|
|
| This is a research PoC for the huntr Model File Vulnerability program. All |
| testing was performed locally. |
|
|