CVE-2022-35994: Reachable Assertion (CWE-617)
value: TensorFlow is an open source platform for machine learning. When `CollectiveGather` receives an scalar input `input`, it gives a `CHECK` fails that can be used to trigger a denial of service attack. We have patched the issue in GitHub commit c1f491817dec39a26be3c574e86a88c30f3c4770. The fix will be included in TensorFlow 2.10.0. We will also cherrypick this commit on TensorFlow 2.9.1, TensorFlow 2.8.1, and TensorFlow 2.7.2, as these are also affected and still in supported range. There are no known workarounds for this issue.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 7.5
Published: 2022-09-16T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/collective_ops.cc, tensorflow/python/ops/collective_ops_test.py
Commit date: 2022-07-13 14:20:57 -0700
Commit message: Fix for check failure in CollectiveGather op.

The fix is required only for Eager mode, graph mode already checked for input shape in shape inference pass.

PiperOrigin-RevId: 460801136

Diff: diff --git a/tensorflow/core/kernels/collective_ops.cc b/tensorflow/core/kernels/collective_ops.cc
index 7045b106d730c..fd8146361df95 100644
--- a/tensorflow/core/kernels/collective_ops.cc
+++ b/tensorflow/core/kernels/collective_ops.cc
@@ -174,10 +174,14 @@ class CollectiveGatherOpKernel : public CollectiveOpV1Kernel {
 
  protected:
   void ComputeAsyncImpl(OpKernelContext* c, CollectiveExecutor* col_exec,
                         DoneCallback done) override {
     auto output_shape = c->input(0).shape();
+    OP_REQUIRES_ASYNC(c, output_shape.dims() > 0,
+                      errors::InvalidArgument("input should have rank > 0, ",
+                                              "recieved ", output_shape.dims()),
+                      done);
     output_shape.set_dim(
         0, output_shape.dim_size(0) * col_params_->group.group_size);
     col_params_->instance.shape = output_shape;
 
     // Allocate output on the first pass through this function.  This must be
diff --git a/tensorflow/python/ops/collective_ops_test.py b/tensorflow/python/ops/collective_ops_test.py
index a95896c0a23a0..5b57956996b8a 100644
--- a/tensorflow/python/ops/collective_ops_test.py
+++ b/tensorflow/python/ops/collective_ops_test.py
@@ -449,10 +449,24 @@ class CollectiveOpTest(test.TestCase):
         context.LogicalDeviceConfiguration(),
         context.LogicalDeviceConfiguration()
     ])
     context.ensure_initialized()
 
+  @test_util.run_v2_only
+  def testCollectiveGatherShapeCheckFailure(self):
+    with self.assertRaisesRegex(errors.InvalidArgumentError,
+                                'input should have rank > 0'):
+      collective_ops.gen_collective_ops.CollectiveGather(
+          input=1,
+          group_size=1,
+          group_key=1,
+          instance_key=1,
+          shape=(3, 3, 3),
+          communication_hint='auto',
+          timeout_seconds=0,
+          name='')
+
     @def_function.function
     def run_all_reduce():
       group_key = 10
       instance_key = 20
       t0 = [1, 2, 3, 4]

Fixed code:     OP_REQUIRES_ASYNC(c, output_shape.dims() > 0,
                      errors::InvalidArgument("input should have rank > 0, ",
                                              "recieved ", output_shape.dims()),
                      done);
  @test_util.run_v2_only
  def testCollectiveGatherShapeCheckFailure(self):
    with self.assertRaisesRegex(errors.InvalidArgumentError,
                                'input should have rank > 0'):
      collective_ops.gen_collective_ops.CollectiveGather(
          input=1,
          group_size=1,
          group_key=1,
          instance_key=1,
          shape=(3, 3, 3),
          communication_hint='auto',
          timeout_seconds=0,
          name='')