Views
No views yet
.armnn model load)Security research artifact for responsible disclosure (Protect AI / huntr Model File Vulnerability program). These files are malformed Arm NN model files that trigger memory-safety bugs inARM-software/armnn'sarmnnDeserializerwhen loaded. They are crash/where-it-corrupts proof-of-concepts, not weaponized exploits. Do not load them with an unhardened build outside a sandbox.
ARM-software/armnn — armnnDeserializer
(src/armnnDeserializer/Deserializer.cpp → armnnUtils::Permute), reached via the public API
armnnDeserializer::IDeserializer::CreateNetworkFromBinary.
Version: HEAD f8beb5a9 (v26.01). Format: .armnn (Arm NN FlatBuffers).
Class: CWE-787 (OOB Write) / CWE-190 (Integer Overflow) / CWE-125 (OOB Read) / CWE-843 (Type Confusion).ParseConstant (default m_WeightsLayoutScheme <= 0 path) permutes constant-tensor weights into a freshly
allocated buffer. Two validation gaps make this memory-unsafe when the model is untrusted:TensorShape::GetNumElements() multiplies the dimensions in unsigned int
with no overflow check (src/armnn/Tensor.cpp:181), and GetNumBytes() = GetDataTypeSize() * GetNumElements()
likewise. A dimension product of 2^32 wraps to 0, so permuteBuffer = new unsigned char[GetNumBytes()]
is under-allocated, while armnnUtils::Permute iterates the true product of dimensions → OOB write.ToConstTensor only checks data->size() == GetNumElements() (element
count); it never verifies the union member width (ByteData/ShortData/IntData/LongData = 1/2/4/8 bytes)
matches the tensor's declared dataType width. This (a) lets the over-read read GetNumBytes() from a smaller
buffer → OOB read whose content surfaces in the returned INetwork (heap disclosure), and (b) lets the
source stay larger than the destination so the OOB write content is attacker-supplied.armnnUtils::Permute/PermuteLoop::Unroll receive srcEnd/dstEnd but only null-check them — they are never
enforced as bounds at the memcpy.models/)| file | effect when loaded (under ASAN) |
|---|---|
combined_chain.armnn | one model, both bugs — two ConstantLayers (write + leak), single CreateNetworkFromBinary call. ASAN aborts at the first OOB (write-first → WRITE). |
constweight_controlled_write.armnn | controlled-content heap OOB WRITE — dims=[1,1,2,2147483680] (product 2^32+64 → wraps to 64), dataType=QAsymmU8 (dst=64 B), data via IntData (256 B of 0x41). Overflowing byte written at dstOff=64 is the attacker's 0x41. |
constweight_widthconfusion.armnn | heap OOB READ / info-leak — Float32 tensor (GetNumBytes()=4000) with ByteData of only 1000 B → 3000 B over-read copied into the network constant. |
constweight_allocoverflow.armnn | minimal length-only WRITE variant — dims=[65536,65536,1,1], empty data → new[0] → WRITE of size 4 at offset 0. |
*.json are the human-readable sources (compiled to .armnn with flatc -b ArmnnSchema.fbs <f>.json).
asan_*.txt are the full AddressSanitizer reports.1# 1. flatbuffers v24.3.25 (flatc + libflatbuffers.a)
2# 2. Build armnn deserializer only, no ACL backends, with ASAN:
3cmake -GNinja .. -DBUILD_ARMNN_DESERIALIZER=ON -DARMNNREF=OFF -DBUILD_UNIT_TESTS=OFF \
4 -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_COMPILER=clang++ \
5 -DCMAKE_CXX_FLAGS="-fsanitize=address -g -O1" \
6 -DFLATC_DIR=<flatc_dir> -DFLATBUFFERS_INCLUDE_PATH=<inc> -DFLATBUFFERS_LIBRARY=<libflatbuffers.a>
7ninja armnnDeserializer
8# (Deserializer.cpp + armnnUtils compiled with -DNDEBUG to match a Release build, so the
9# flatbuffers debug assert is removed and the real OOB access is exercised.)
10
11# 3. A ~15-line driver that calls IDeserializer::CreateNetworkFromBinary(bytes):
12./driver models/constweight_controlled_write.armnn # -> AddressSanitizer: heap-buffer-overflow WRITE
13./driver models/constweight_widthconfusion.armnn # -> AddressSanitizer: heap-buffer-overflow READ
14./driver models/combined_chain.armnn # -> WRITE (first layer)