CVE-2022-36000: NULL Pointer Dereference (CWE-476)
value: TensorFlow is an open source platform for machine learning. When `mlir::tfg::ConvertGenericFunctionToFunctionDef` is given empty function attributes, it gives a null dereference. We have patched the issue in GitHub commit aed36912609fc07229b4d0a7b44f3f48efc00fd0. 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 dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2022-09-16T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/linalg/linalg_ops_common.cc, tensorflow/python/kernel_tests/linalg/eig_op_test.py
Commit date: 2022-07-18 09:21:45 -0700
Commit message: Check correct input/output scalar types for LinearAlgebraOp.

If calling the `tf.raw_ops` versions, it's possible to provide bad output scalar
types (e.g. for `Eig`), causing a failing check when trying to actually compute
outputs.  Here we add an appropriate input validation check.

NOTE: no test is added because it's impossible to trigger these using the
official public API.
PiperOrigin-RevId: 461637318

Diff: diff --git a/tensorflow/core/kernels/linalg/linalg_ops_common.cc b/tensorflow/core/kernels/linalg/linalg_ops_common.cc
index 5529e04ab774f..a64bdbed18225 100644
--- a/tensorflow/core/kernels/linalg/linalg_ops_common.cc
+++ b/tensorflow/core/kernels/linalg/linalg_ops_common.cc
@@ -13,18 +13,21 @@ See the License for the specific language governing permissions and
 limitations under the License.
 ==============================================================================*/
 
 #include "tensorflow/core/kernels/linalg/linalg_ops_common.h"
 
+#include <initializer_list>
 #include <utility>
 
 #include "third_party/eigen3/Eigen/Core"
 #include "tensorflow/core/framework/device_base.h"
 #include "tensorflow/core/framework/kernel_def_builder.h"
 #include "tensorflow/core/framework/op_kernel.h"
 #include "tensorflow/core/framework/tensor_shape.h"
+#include "tensorflow/core/framework/types.h"
 #include "tensorflow/core/lib/core/errors.h"
+#include "tensorflow/core/platform/errors.h"
 #include "tensorflow/core/platform/logging.h"
 #include "tensorflow/core/platform/types.h"
 
 namespace tensorflow {
 
@@ -150,10 +153,14 @@ void LinearAlgebraOp<InputScalar, OutputScalar>::AnalyzeInputs(
     const int64_t num_rows = in.dim_size(row_dimension);
     const int64_t num_cols = in.dim_size(col_dimension);
     input_matrix_shapes->emplace_back(
         std::initializer_list<int64_t>({num_rows, num_cols}));
     inputs->emplace_back(&in);
+    OP_REQUIRES(
+        context, in.dtype() == DataTypeToEnum<InputScalar>::v(),
+        errors::InvalidArgument("Invalid input dtype ", in.dtype(), " vs ",
+                                DataTypeToEnum<InputScalar>::v()));
   }
   // Have the derived class validate that the inputs are as expected.
   ValidateInputMatrixShapes(context, *input_matrix_shapes);
 }
 
@@ -210,10 +217,15 @@ void LinearAlgebraOp<InputScalar, OutputScalar>::PrepareOutputs(
     }
     if (!reused_input) {
       OP_REQUIRES_OK(context, context->allocate_output(
                                   output_idx, output_tensor_shape, &out));
     }
+    OP_REQUIRES(
+        context, out->dtype() == DataTypeToEnum<OutputScalar>::v(),
+        errors::InvalidArgument("Invalid output dtype ", out->dtype(), " vs ",
+                                DataTypeToEnum<OutputScalar>::v()));
+
     outputs->emplace_back(out);
   }
 }
 
 template <class InputScalar, class OutputScalar>
diff --git a/tensorflow/python/kernel_tests/linalg/eig_op_test.py b/tensorflow/python/kernel_tests/linalg/eig_op_test.py
index 37ba5b0cc8959..33ce04f50d3ba 100644
--- a/tensorflow/python/kernel_tests/linalg/eig_op_test.py
+++ b/tensorflow/python/kernel_tests/linalg/eig_op_test.py
@@ -16,12 +16,14 @@
 
 import numpy as np
 
 from tensorflow.python.framework import constant_op
 from tensorflow.python.framework import dtypes as dtypes_lib
+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_linalg_ops
 from tensorflow.python.ops import gradient_checker_v2
 from tensorflow.python.ops import linalg_ops
 from tensorflow.python.ops import math_ops
 from tensorflow.python.ops import random_ops
 from tensorflow.python.ops import sort_ops
@@ -86,10 +88,20 @@ class EigTest(test.TestCase):
       self.assertAllClose(
           np.matmul(v, v.transpose()), np.eye(32, dtype=np.float32), atol=2e-3)
       self.assertAllClose(matrix,
                           np.matmul(np.matmul(v, np.diag(e)), v.transpose()))
 
+  def testMismatchedDtypes(self):
+    tensor = constant_op.constant([[0, 1], [2, 3]], dtype=dtypes_lib.float32)
+    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
+                                "Invalid output dtype"):
+      self.evaluate(
+          gen_linalg_ops.eig(
+              input=tensor,
+              Tout=dtypes_lib.complex128,  # Expected dtype: complex64.
+              compute_v=True))
+
 
 def SortEigenValues(e):
   perm = np.argsort(e.real + e.imag, -1)
   return np.take(e, perm, -1)
 

Fixed code: #include <initializer_list>
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/platform/errors.h"
    OP_REQUIRES(
        context, in.dtype() == DataTypeToEnum<InputScalar>::v(),
        errors::InvalidArgument("Invalid input dtype ", in.dtype(), " vs ",
                                DataTypeToEnum<InputScalar>::v()));
    OP_REQUIRES(
        context, out->dtype() == DataTypeToEnum<OutputScalar>::v(),
        errors::InvalidArgument("Invalid output dtype ", out->dtype(), " vs ",
                                DataTypeToEnum<OutputScalar>::v()));

from tensorflow.python.framework import errors
from tensorflow.python.ops import gen_linalg_ops
  def testMismatchedDtypes(self):
    tensor = constant_op.constant([[0, 1], [2, 3]], dtype=dtypes_lib.float32)
    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "Invalid output dtype"):
      self.evaluate(
          gen_linalg_ops.eig(
              input=tensor,
              Tout=dtypes_lib.complex128,  # Expected dtype: complex64.
              compute_v=True))