• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1## TFSA-2020-005: Out of bounds access in TFLite operators
2
3### CVE Number
4CVE-2020-15211
5
6### Impact
7In TensorFlow Lite, saved models in the flatbuffer format use a double indexing
8scheme: a model has a set of subgraphs, each subgraph has a set of operators and
9each operator has a set of input/output tensors. The flatbuffer format uses
10indices for the tensors, indexing into an array of tensors that is owned by the
11subgraph. This results in a pattern of double array indexing when trying to
12[get the data of each
13tensor](https://github.com/tensorflow/tensorflow/blob/0e68f4d3295eb0281a517c3662f6698992b7b2cf/tensorflow/lite/kernels/kernel_util.cc#L36):
14```cc
15  return &context->tensors[node->inputs->data[index]];
16```
17
18However, some operators can have some tensors be optional. To handle this
19scenario, the flatbuffer model uses a negative `-1` value as [index for these tensors](https://github.com/tensorflow/tensorflow/blob/0e68f4d3295eb0281a517c3662f6698992b7b2cf/tensorflow/lite/c/common.h#L82):
20```cc
21#define kTfLiteOptionalTensor (-1)
22```
23
24This results in [special casing during validation at model loading
25time](https://github.com/tensorflow/tensorflow/blob/0e68f4d3295eb0281a517c3662f6698992b7b2cf/tensorflow/lite/core/subgraph.cc#L566-L580):
26```cc
27  for (int i = 0; i < length; i++) {
28    int index = indices[i];
29    // Continue if index == kTfLiteOptionalTensor before additional comparisons
30    // below, size_t(-1) is always >= context_tensors_size.
31    if (index == kTfLiteOptionalTensor) {
32      continue;
33    }
34    if (index < 0 || static_cast<size_t>(index) >= context_.tensors_size) {
35      ReportError(
36          "Invalid tensor index %d in %s. The subgraph has %d tensors\n", index,
37          label, context_.tensors_size);
38      consistent_ = false;
39      return kTfLiteError;
40    }
41  }
42```
43
44Unfortunately, this means that the `-1` index is a valid tensor index for any
45operator, including those that don't expect optional inputs and including for
46output tensors. Thus, this allows writing and reading from outside the bounds of
47heap allocated arrays, although only at a specific offset from the start of
48these arrays.
49
50This results in both read and write gadgets, albeit very limited in scope.
51
52### Vulnerable Versions
53TensorFlow 1.15.0, 1.15.1, 1.15.2, 1.15.3, 2.0.0, 2.0.1, 2.0.2, 2.1.0, 2.1.1,
542.2.0, 2.3.0.
55
56### Patches
57We have patched the issue in several commits
58([46d5b0852](https://github.com/tensorflow/tensorflow/commit/46d5b0852),
59[00302787b7](https://github.com/tensorflow/tensorflow/commit/00302787b7),
60[e11f5558](https://github.com/tensorflow/tensorflow/commit/e11f5558),
61[cd31fd0ce](https://github.com/tensorflow/tensorflow/commit/cd31fd0ce),
62[1970c21](https://github.com/tensorflow/tensorflow/commit/1970c21), and
63[fff2c83](https://github.com/tensorflow/tensorflow/commit/fff2c83)). We will
64release patch releases for all versions between 1.15 and 2.3.
65
66We recommend users to upgrade to TensorFlow 1.15.4, 2.0.3, 2.1.2, 2.2.1, or
672.3.1.
68
69### Workarounds
70A potential workaround would be to add a custom `Verifier` to the model loading
71code to ensure that only operators which accept optional inputs use the `-1`
72special value and only for the tensors that they expect to be optional. Since
73this allow-list type approach is erro-prone, we advise upgrading to the patched
74code.
75
76### For more information
77Please consult [our security
78guide](https://github.com/tensorflow/tensorflow/blob/master/SECURITY.md) for
79more information regarding the security model and how to contact us with issues
80and questions.
81
82### Attribution
83This vulnerability has been reported by members of the Aivul Team from Qihoo
84360.
85