YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PyTorch v1.3 TorchScript odd-dictionary heap OOB read
malicious_odd_dict.pt is a TorchScript archive whose data.pkl member is the
protocol-2 stream PROTO 2, MARK, BININT1(1), DICT, STOP. The DICT opcode
therefore receives one stack item after its MARK, rather than an even number
of key/value items.
In PyTorch v1.3.1, torch::jit::Unpickler::readInstruction() handles DICT
by iterating over the remaining stack in pairs and reads stack_[i + 1]
without first validating that a value exists. The supplied model reaches that
parser through torch.jit.load().
Files
control_valid.ptโ a normally saved TorchScript identity module.malicious_odd_dict.ptโ the malformed model file to upload and test.build_and_verify.pyโ regenerates both model files and exercises the normal Python loading path.verify_unpickler.cppandrun_asan_verification.shโ a focused, CPU-only ASAN verifier compiled against the pinned v1.3.1 unpickler source.verify_report.jsonโ observed verification results.
Quick reproduction
The normal loading path is exercised with PyTorch 1.3 on CPU:
python build_and_verify.py --load-control
python build_and_verify.py --load-malicious
The control loads successfully. The malicious model reaches the unpickler,
then fails later because the resulting root object is not a ScriptModule. To
observe the underlying out-of-bounds read, compile the same v1.3.1
unpickler.cpp with AddressSanitizer. The following has been verified in a
Linux CPU container with PyTorch 1.3 headers and libraries:
export PYTORCH_SRC=/path/to/pytorch-v1.3.1-source
bash run_asan_verification.sh
The expected ASAN stack trace contains torch::jit::Unpickler::readInstruction
at the DICT handling block and reports a heap-buffer-overflow while copying
the missing dictionary value.
Impact
An attacker who can supply a .pt TorchScript model can make the CPU model
loader read past the std::vector<c10::IValue> allocation during parsing. The
bug is a memory-safety violation in model loading; the supplied model uses no
Python pickle globals, custom operators, network access, or GPU.