Arm NN .armnn Deserializer Stack Buffer Overflow via TensorInfo.dimensionSpecificity

Summary

This repository contains a benign proof of concept for a schema-valid Arm NN FlatBuffers model artifact that triggers a stack-buffer-overflow in the Arm NN v26.01 .armnn deserializer.

The bug is reached while converting serialized TensorInfo data into Arm NN's runtime TensorInfo. The deserializer allocates a fixed stack array:

bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];

armnn::MaxNumOfTensorDimensions is 5, but the serialized dimensionSpecificity vector length is copied without a bounds check:

auto dimensionSpecificity = tensorPtr->dimensionSpecificity();
size = dimensionSpecificity->size();
for (unsigned int i = 0; i < size; ++i)
{
    dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
}

A .armnn artifact can therefore provide more than 5 dimensionSpecificity entries and write past the fixed stack array during deserialization.

The PoC is intentionally non-destructive. It contains no shell command, network callback, persistence, credential access, or payload beyond the model file fields needed to reach the parser bug.

Impact

  • Artifact-carried native memory corruption during .armnn model deserialization.
  • FlatBuffers verification accepts the artifact before the Arm NN loader reaches the vulnerable code path.
  • A release loader segfaults on the main artifact.
  • ASAN/UBSAN identifies a stack-buffer-overflow write in armnnDeserializer::ToTensorInfo() at Deserializer.cpp:756.
  • ModelScan 0.8.8 reports zero issues because .armnn is not scanned.

This is not a Python exception and not a malformed CLI invocation. The trigger is contained in the serialized model artifact.

Affected Version Tested

  • Arm NN SDK v26.01
  • Local tested commit: 600c0004a2a7a2d600a3bce22ef83193de1dde57
  • FlatBuffers 24.3.25
  • ModelScan 0.8.8
  • Linux x86_64 local build

The same unchecked loop was also observed in a local checkout of Arm NN v25.11, but this repository's primary verification evidence is for v26.01.

Files

artifacts/dim_spec_len1024_oob_write_crash.armnn
  Main PoC. FlatBuffers verifier accepts it; release loader segfaults; ASAN
  reports a stack-buffer-overflow write.

artifacts/dim_spec_len6_oob_write.armnn
  Minimal one-byte-overflow PoC. Useful for showing the smallest vector length
  that crosses MaxNumOfTensorDimensions.

artifacts/dim_spec_len1024_oob_write_crash.json
  JSON source for the main PoC artifact.

scripts/build_dim_specificity_stack_overflow.py
  Generator used to create the PoC artifacts from Arm NN's FlatBuffers schema.

evidence/verification_summary.json
  Captured local verifier, release-loader, control-loader, and ASAN outputs.

evidence/followup_notes_dim_specificity_stack_overflow.md
  Additional notes, duplicate-check notes, and command summary.

evidence/sha256.txt
  SHA256 hashes for uploaded artifacts and scripts.

Reproduction

The commands below assume a local Arm NN v26.01 build environment equivalent to the one used during verification. The paths under /workspace/arm_nn_flatbuffers refer to the local build tree used to produce the evidence files.

1. Confirm FlatBuffers Verifier Accepts the Artifact

/workspace/arm_nn_flatbuffers/lab/verify_armnn_flatbuffer \
  artifacts/dim_spec_len1024_oob_write_crash.armnn

Expected output:

VERIFY_OK bytes=2484

2. Confirm a Valid Control Model Loads

/workspace/arm_nn_flatbuffers/lab/load_armnn \
  /workspace/arm_nn_flatbuffers/lab/control_valid.armnn

Expected output:

LOAD_OK network=1

3. Trigger the Release Loader Crash

/workspace/arm_nn_flatbuffers/lab/load_armnn \
  artifacts/dim_spec_len1024_oob_write_crash.armnn

Observed locally:

SIGSEGV

The captured verification summary records the release loader return code as -11.

4. Trigger the ASAN/UBSAN Evidence

ASAN_OPTIONS=abort_on_error=0:symbolize=1:halt_on_error=1 \
  /workspace/arm_nn_flatbuffers/lab/followup_armnn_dim_specificity/load_armnn_followup_asan \
  artifacts/dim_spec_len1024_oob_write_crash.armnn

Observed locally:

runtime error: index 5 out of bounds for type 'bool [5]'
runtime error: store to address ... with insufficient space for an object of type 'bool'
ERROR: AddressSanitizer: stack-buffer-overflow
WRITE of size 1
#0 armnnDeserializer::ToTensorInfo(...) Deserializer.cpp:756
#1 armnnDeserializer::IDeserializer::DeserializerImpl::SetupInputLayers(...) Deserializer.cpp:1089
#2 armnnDeserializer::IDeserializer::DeserializerImpl::CreateNetworkFromGraph(...) Deserializer.cpp:939
#3 armnnDeserializer::IDeserializer::DeserializerImpl::CreateNetworkFromBinary(...) Deserializer.cpp:882

5. Scanner Behavior

/workspace/arm_nn_flatbuffers/.venv/bin/modelscan \
  -p artifacts/dim_spec_len1024_oob_write_crash.armnn \
  -r json --show-skipped

Observed locally:

{
  "total_issues": 0,
  "scanned": {"total_scanned": 0},
  "skipped": {
    "total_skipped": 1,
    "skipped_files": [
      {
        "category": "SCAN_NOT_SUPPORTED",
        "source": "dim_spec_len1024_oob_write_crash.armnn"
      }
    ]
  }
}

This is not claimed as a standalone scanner bypass; it is included to document that the dangerous artifact is not inspected by the scanner in this environment.

Root Cause Details

In Arm NN v26.01, include/armnn/Types.hpp defines:

constexpr unsigned int MaxNumOfTensorDimensions = 5U;

In src/armnnDeserializer/Deserializer.cpp, ToTensorInfo() allocates a fixed-size stack buffer using that value:

bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];

The deserializer then uses the serialized vector's length as the copy bound:

size = dimensionSpecificity->size();
for (unsigned int i = 0; i < size; ++i)
{
    dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
}

The artifact dim_spec_len1024_oob_write_crash.armnn sets TensorInfo.dimensions to a normal one-dimensional tensor while setting TensorInfo.dimensionSpecificity to a much longer boolean vector. The FlatBuffers schema permits the vector, the FlatBuffers verifier accepts the serialized file, and the Arm NN deserializer writes past the fixed stack array.

Hashes

a73e0e4350808d6c82ea8fe4066e02c638b00010c34539c4604a6720f122df36  artifacts/dim_spec_len1024_oob_write_crash.armnn
98c259b1abac9b138b68427d0b6b15e958bcd0a756dac485ce0377cef9017ef9  artifacts/dim_spec_len1024_oob_write_crash.json
990b49d7cfa3a977f7947d5d4c5724be8bc3e44aa84d82e1b3424666f4b51470  artifacts/dim_spec_len6_oob_write.armnn
098e6b9a788daaeac94c7d76d99ff03991880cde620c9c856561b344819e4ba3  scripts/build_dim_specificity_stack_overflow.py

Limitations

  • This PoC demonstrates memory corruption and crash; it does not demonstrate code execution.
  • Exploitability beyond controlled stack write/crash was not attempted.
  • The ASAN binary used for verification is not uploaded because it is a large local build artifact. The captured sanitizer output is included under evidence/verification_summary.json.
  • ModelScan not supporting .armnn is not itself the vulnerability; the vulnerability is the Arm NN native deserializer memory corruption.

Duplicate Check Notes

Searches were performed for Arm NN dimensionSpecificity, ToTensorInfo, Deserializer.cpp, stack-buffer-overflow, and FlatBuffers deserializer crash terms. No public matching advisory or issue was found during local triage.

Checked source areas:

  • Arm NN v26.01 src/armnnDeserializer/Deserializer.cpp
  • Arm NN v26.01 include/armnn/Types.hpp
  • Arm NN GitHub security/advisory pages
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support