CVE-2022-29196: Improper Validation of Specified Quantity in Input (CWE-1284)
value: TensorFlow is an open source platform for machine learning. Prior to versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4, the implementation of `tf.raw_ops.Conv3DBackpropFilterV2` does not fully validate the input arguments. This results in a `CHECK`-failure which can be used to trigger a denial of service attack. The code does not validate that the `filter_sizes` argument is a vector. Versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4 contain a patch for this issue.
CWE description: The product receives input that is expected to specify a quantity (such as size or length), but it does not validate or incorrectly validates that the quantity has the required properties.
CVSS v3 base score: 5.5
Published: 2022-05-20T22:16Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/conv_grad_ops_3d.cc, tensorflow/python/kernel_tests/nn_ops/conv3d_backprop_filter_v2_grad_test.py
Commit date: 2022-04-29 15:20:38 -0700
Commit message: Fix failed check in Conv3DBackpropFilterV2.

Passing in a rank-0 `filter_size` causes a check fail and crash,
coming from a `filter_size.vec<>()` call.  Here we check the size
first.

PiperOrigin-RevId: 445517122

Diff: diff --git a/tensorflow/core/kernels/conv_grad_ops_3d.cc b/tensorflow/core/kernels/conv_grad_ops_3d.cc
index 9364ee92f5c40..09d3365564d8a 100644
--- a/tensorflow/core/kernels/conv_grad_ops_3d.cc
+++ b/tensorflow/core/kernels/conv_grad_ops_3d.cc
@@ -739,10 +739,14 @@ class Conv3DBackpropFilterOp : public OpKernel {
     const TensorShape& out_backprop_shape = out_backprop.shape();
 
     TensorShape filter_shape;
     if (takes_shape_) {
       const Tensor& filter_sizes = context->input(1);
+      OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
+                  errors::InvalidArgument(
+                      "filter_sizes shape must be rank 1 but is rank ",
+                      filter_sizes.shape().dims()));
       OP_REQUIRES_OK(context, TensorShapeUtils::MakeShape(
                                   filter_sizes.vec<int32>(), &filter_shape));
     } else {
       filter_shape = context->input(1).shape();
     }
@@ -873,10 +877,14 @@ class Conv3DCustomBackpropFilterOp : public OpKernel {
     const TensorShape& out_backprop_shape = out_backprop.shape();
 
     TensorShape filter_shape;
     if (takes_shape_) {
       const Tensor& filter_sizes = context->input(1);
+      OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
+                  errors::InvalidArgument(
+                      "filter_sizes shape must be rank 1 but is rank ",
+                      filter_sizes.shape().dims()));
       OP_REQUIRES_OK(context, TensorShapeUtils::MakeShape(
                                   filter_sizes.vec<int32>(), &filter_shape));
     } else {
       filter_shape = context->input(1).shape();
     }
@@ -1636,10 +1644,14 @@ class Conv3DBackpropFilterOp<GPUDevice, T> : public OpKernel {
     const TensorShape& out_backprop_shape = out_backprop.shape();
 
     TensorShape filter_shape;
     if (takes_shape_) {
       const Tensor& filter_sizes = context->input(1);
+      OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
+                  errors::InvalidArgument(
+                      "filter_sizes shape must be rank 1 but is rank ",
+                      filter_sizes.shape().dims()));
       OP_REQUIRES_OK(context, tensor::MakeShape(filter_sizes, &filter_shape));
     } else {
       filter_shape = context->input(1).shape();
     }
 
diff --git a/tensorflow/python/kernel_tests/nn_ops/conv3d_backprop_filter_v2_grad_test.py b/tensorflow/python/kernel_tests/nn_ops/conv3d_backprop_filter_v2_grad_test.py
index f6e84d3c339f3..c92bb747acfa6 100644
--- a/tensorflow/python/kernel_tests/nn_ops/conv3d_backprop_filter_v2_grad_test.py
+++ b/tensorflow/python/kernel_tests/nn_ops/conv3d_backprop_filter_v2_grad_test.py
@@ -16,10 +16,11 @@
 
 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 gradient_checker
 from tensorflow.python.ops import nn_ops
 import tensorflow.python.ops.nn_grad  # pylint: disable=unused-import
@@ -56,8 +57,25 @@ class Conv3DBackpropFilterV2GradTest(test.TestCase):
               output, filter_shape)
           print("conv3d_backprop_filter gradient err = %g " % err)
           err_tolerance = 1e-3
           self.assertLess(err, err_tolerance)
 
+  def testBadFilterShape(self):
+    strides = [1, 1, 1, 1, 1]
+    padding = "VALID"
+    tin = constant_op.constant(
+        .5053710941, shape=[2, 2, 2, 2, 1], dtype=dtypes.float32)
+    filter_sizes = constant_op.constant(0, shape=[], dtype=dtypes.int32)
+    out_backprop = constant_op.constant(
+        .5053710941, shape=[2, 2, 2, 2, 1], dtype=dtypes.float32)
+
+    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
+                                "must be rank 1"):
+      nn_ops.conv3d_backprop_filter_v2(
+          input=tin,
+          filter_sizes=filter_sizes,
+          out_backprop=out_backprop,
+          strides=strides,
+          padding=padding)
 
 if __name__ == "__main__":
   test.main()

Fixed code:       OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
                  errors::InvalidArgument(
                      "filter_sizes shape must be rank 1 but is rank ",
                      filter_sizes.shape().dims()));
      OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
                  errors::InvalidArgument(
                      "filter_sizes shape must be rank 1 but is rank ",
                      filter_sizes.shape().dims()));
      OP_REQUIRES(context, TensorShapeUtils::IsVector(filter_sizes.shape()),
                  errors::InvalidArgument(
                      "filter_sizes shape must be rank 1 but is rank ",
                      filter_sizes.shape().dims()));
from tensorflow.python.framework import errors
  def testBadFilterShape(self):
    strides = [1, 1, 1, 1, 1]
    padding = "VALID"
    tin = constant_op.constant(
        .5053710941, shape=[2, 2, 2, 2, 1], dtype=dtypes.float32)
    filter_sizes = constant_op.constant(0, shape=[], dtype=dtypes.int32)
    out_backprop = constant_op.constant(
        .5053710941, shape=[2, 2, 2, 2, 1], dtype=dtypes.float32)

    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "must be rank 1"):
      nn_ops.conv3d_backprop_filter_v2(
          input=tin,
          filter_sizes=filter_sizes,
          out_backprop=out_backprop,
          strides=strides,
          padding=padding)