YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
Samsung ONE Circle ArgMax out-of-range axis heap OOB write PoC
Summary
Samsung ONE's Circle interpreter 1.30.1 does not validate that a model-controlled ArgMax axis is smaller than the input rank. ArgMax::configure() allocates an output Shape with rank - 1 elements, but when axis == rank the loop skips no dimension and writes rank elements into it. In the release binary, the assertion in Shape::dim() is disabled, so the last assignment is a one-past-the-end heap write. The same invalid axis reaches the PAL ArgMax implementation during execution and produces a second heap out-of-bounds write.
The supplied model is a valid 700-byte CIR0 file. It has a rank-3 float input ([2, 3, 4]) and an inline int32 axis value of 3. The baseline differs only at the axis byte and uses the valid value 1.
Tested with Samsung ONE circle-interpreter 1.30.1 (tag commit ede4bacc61157f37de895282e1a4b6f19a65afd9) on CPU.
Root cause
In compiler/luci-interpreter/src/kernels/ArgMax.cpp, ArgMax::configure() performs only a lower-bound assertion:
Shape output_shape(num_dims - 1);
int axis_value = getTensorData<int32_t>(axis())[0];
if (axis_value < 0)
axis_value = axis_value + num_dims;
assert(axis_value >= 0);
int j = 0;
for (int i = 0; i < num_dims; i++)
{
if (i == axis_value)
continue;
output_shape.dim(j++) = input_shape.dim(i);
}
There is no axis_value < num_dims check. compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h implements the mutable accessor using an assertion followed by unchecked std::vector::operator[]:
int32_t &dim(int i)
{
assert(i >= 0 && i < static_cast<int>(_dims.size()));
return _dims[i];
}
The loader in compiler/luci-interpreter/src/loader/nodes/ArgMax.cpp connects the model-controlled dimension tensor directly to the kernel.
Static artifact verification
Install the small FlatBuffer schema package and verify/rebuild the model:
python -m pip install -r requirements.txt
python build_and_verify.py --output rebuilt_malicious.circle --report rebuilt_report.json
The verifier confirms that both files have the CIR0 identifier and that rebuilding the baseline by replacing its inline axis with the rank produces the uploaded malicious file byte-for-byte.
Dynamic reproduction
Download and extract the official Samsung ONE 1.30.1 Ubuntu release:
curl -LO https://github.com/Samsung/ONE/releases/download/1.30.1/onecc-jammy-1.30.1.tar.gz
mkdir onecc
tar -xzf onecc-jammy-1.30.1.tar.gz -C onecc
Run the valid baseline. The input argument is a prefix; circle-interpreter appends 0 and reads malicious_argmax_axis_oob.input0:
docker run --rm -v "$PWD/onecc:/one:ro" -v "$PWD:/poc:ro" ubuntu:22.04 bash -lc \
'LD_LIBRARY_PATH=/one/lib /one/bin/circle-interpreter \
/poc/baseline_argmax.circle \
/poc/malicious_argmax_axis_oob.input \
/tmp/baseline.output'
The baseline exits successfully. Run the malicious model under Valgrind:
docker run --rm -v "$PWD/onecc:/one:ro" -v "$PWD:/poc:ro" ubuntu:22.04 bash -lc \
'apt-get update >/dev/null && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends valgrind >/dev/null && \
LD_LIBRARY_PATH=/one/lib valgrind --tool=memcheck --track-origins=yes \
/one/bin/circle-interpreter \
/poc/malicious_argmax_axis_oob.circle \
/poc/malicious_argmax_axis_oob.input \
/tmp/malicious.output'
Valgrind 3.18.1 reports both of the following before terminating because of heap corruption:
Invalid write of size 4
at luci_interpreter::kernels::ArgMax::configure()
Address ... is 0 bytes after a block of size 8 alloc'd
Invalid write of size 4
at luci_interpreter::kernels::ArgMax::execute()
Address ... is 0 bytes after a block of size 24 alloc'd
The complete captured output is in valgrind_report.txt.
Security impact
An untrusted Circle model can cause attacker-controlled native heap writes during the first inference/configuration path. This is CWE-787 memory corruption rather than a verifier-only bypass or an allocation-only denial of service. Depending on allocator state and the surrounding objects, native heap corruption can affect process integrity and may provide a path toward code execution. This PoC deliberately demonstrates only the bounded out-of-bounds writes and does not attempt weaponization.
Relationship to the earlier TensorFlow Lite issue
The vulnerable Circle logic mirrors the historical TensorFlow Lite ArgMax issue CVE-2021-29603. TensorFlow fixed its implementation by requiring both axis >= 0 and axis < NumDimensions(input), but Samsung ONE Circle 1.30.1 still lacks the upper-bound validation. This report concerns the independently affected Circle interpreter and Circle model format.
Recommended fix
Reject the model before constructing the output shape unless the normalized axis satisfies 0 <= axis_value && axis_value < num_dims. Use a runtime validation that remains enabled in release builds rather than assert(). Apply the same validated axis to both configuration and execution, and add regression tests for axis == rank, axis > rank, and negative axes that remain invalid after normalization.