CVE-2022-21730 (published 2022-02-03T11:15Z)

Tensorflow is an Open Source Machine Learning Framework. The implementation of `FractionalAvgPoolGrad` does not consider cases where the input tensors are invalid allowing an attacker to read from outside of bounds of heap. The fix will be included in TensorFlow 2.8.0. We will also cherrypick this commit on TensorFlow 2.7.1, TensorFlow 2.6.3, and TensorFlow 2.5.3, as these are also affected and still in supported range.

Severity: MEDIUM
CVSS v2 base score: 5.5 (AV:N/AC:L/Au:S/C:P/I:N/A:P)
CVSS v3 base score: 8.1, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/tensorflow/tensorflow
commit_details: repo_url: https://github.com/tensorflow/tensorflow
author: Isha Arkatkar
author_date: 2021-12-02 20:57:14-08:00
msg: Add negative bound check for row and column pooling_sequence in FractionalAvgPoolGrad op to avoid out of bound heap access

PiperOrigin-RevId: 413837346
Change-Id: I2b86034101df31bee161abcb781755e236c7bccd
repository: repo_url: https://github.com/tensorflow/tensorflow
repo_name: tensorflow/tensorflow
description: An Open Source Machine Learning Framework for Everyone
repo_language: C++
owner: tensorflow
file_changes: filename: fractional_avg_pool_op.cc
change_type: ModificationType.MODIFY
diff: @@ -311,15 +311,26 @@ class FractionalAvgPoolGradOp : public OpKernel {
     for (int64_t b = 0; b < out_batch; ++b) {
       for (int64_t r = 0; r < out_rows; ++r) {
         const int64_t in_row_start = row_seq_tensor_flat(r);
+
         int64_t in_row_end = overlapping_ ? row_seq_tensor_flat(r + 1)
                                           : row_seq_tensor_flat(r + 1) - 1;
         in_row_end = std::min(in_row_end, in_max_row_index);
+        OP_REQUIRES(context, in_row_start >= 0 && in_row_end >= 0,
+                    errors::InvalidArgument(
+                        "Row sequence tensor values must not be negative, got ",
+                        row_seq_tensor_flat));
+
         for (int64_t c = 0; c < out_cols; ++c) {
           const int64_t in_col_start = col_seq_tensor_flat(c);
           int64_t in_col_end = overlapping_ ? col_seq_tensor_flat(c + 1)
                                             : col_seq_tensor_flat(c + 1) - 1;
           in_col_end = std::min(in_col_end, in_max_col_index);
 
+          OP_REQUIRES(
+              context, in_col_start >= 0 && in_col_end >= 0,
+              errors::InvalidArgument(
+                  "Column sequence tensor values must not be negative, got ",
+                  col_seq_tensor_flat));
           const int64_t num_elements_in_pooling_cell =
               (in_row_end - in_row_start + 1) * (in_col_end - in_col_start + 1);
           const int64_t out_index = (b * out_rows + r) * out_cols + c;

programming_language: C++
filename: fractional_avg_pool_op_test.py
change_type: ModificationType.MODIFY
diff: @@ -20,6 +20,7 @@ import numpy as np
 
 from tensorflow.python.framework import constant_op
 from tensorflow.python.framework import dtypes
+from tensorflow.python.framework import errors
 from tensorflow.python.framework import test_util
 from tensorflow.python.ops import array_ops
 from tensorflow.python.ops import gen_nn_ops
@@ -306,6 +307,32 @@ class FractionalAvgTest(test.TestCase):
           input_b, row_seq, col_seq, overlapping)
       self.assertSequenceEqual(expected.shape, actual.shape)
 
+  def testNegativeSeqValuesForGradOp(self):
+    with self.assertRaisesRegex(
+        errors.InvalidArgumentError,
+        r"Row sequence tensor values must not be negative.*"):
+      y = nn_ops.gen_nn_ops.fractional_avg_pool_grad(
+          orig_input_tensor_shape=[2, 2, 2, 2],
+          out_backprop=[[[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11,
+                                                                      12]]]],
+          row_pooling_sequence=[-10, 1, 2, 3],
+          col_pooling_sequence=[1, 2, 3, 4],
+          overlapping=True)
+
+      self.evaluate(y)
+      with self.assertRaisesRegex(
+          errors.InvalidArgumentError,
+          r"Column sequence tensor values must not be negative.*"):
+        z = nn_ops.gen_nn_ops.fractional_avg_pool_grad(
+            orig_input_tensor_shape=[2, 2, 2, 2],
+            out_backprop=[[[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11,
+                                                                        12]]]],
+            row_pooling_sequence=[10, 1, 2, 3],
+            col_pooling_sequence=[1, 2, -3, 4],
+            overlapping=True)
+
+        self.evaluate(z)
+
 
 class FractionalAvgPoolGradTest(test.TestCase):
   """Tests for FractionalAvgPoolGrad.

programming_language: Python