CVE-2022-23583: Access of Resource Using Incompatible Type ('Type Confusion') (CWE-843)
value: Tensorflow is an Open Source Machine Learning Framework. A malicious user can cause a denial of service by altering a `SavedModel` such that any binary op would trigger `CHECK` failures. This occurs when the protobuf part corresponding to the tensor arguments is modified such that the `dtype` no longer matches the `dtype` expected by the op. In that case, calling the templated binary operator for the binary op would receive corrupted data, due to the type confusion involved. If `Tin` and `Tout` don't match the type of data in `out` and `input_*` tensors then `flat<*>` would interpret it wrongly. In most cases, this would be a silent failure, but we have noticed scenarios where this results in a `CHECK` crash, hence a denial of service. 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.
CWE description: The product allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.
CVSS v3 base score: 6.5
Published: 2022-02-04T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C
Files changed: tensorflow/core/kernels/cwise_ops_common.h
Commit date: 2021-11-12 00:29:24 -0800
Commit message: Validate real and expected type of arguments to cwise ops.

Without this validation, it is possible to trigger a `CHECK`-fail denial of service.

This is a rollforward of a previous commit which was rolled back as it was relying on RTTI. This time we don't use RTTI, we replace `typeid(Tin).name()` with a double function call, `DataTypeString(DataTypeToEnum<Tin>::v())`.

PiperOrigin-RevId: 409340416
Change-Id: I96080b2796729a3a9b65e7c68307ac276070f2f0

Diff: diff --git a/tensorflow/core/kernels/cwise_ops_common.h b/tensorflow/core/kernels/cwise_ops_common.h
index ed4125f45579..fa48717ab1c2 100644
--- a/tensorflow/core/kernels/cwise_ops_common.h
+++ b/tensorflow/core/kernels/cwise_ops_common.h
@@ -85,11 +85,21 @@ class BinaryOp : public BinaryOpShared {
       : BinaryOpShared(ctx, DataTypeToEnum<Tout>::v(),
                        DataTypeToEnum<Tin>::v()) {}
 
   void Compute(OpKernelContext* ctx) override {
     const Tensor& input_0 = ctx->input(0);
+    OP_REQUIRES(ctx, input_0.dtype() == DataTypeToEnum<Tin>::v(),
+                errors::InvalidArgument(
+                    "Expected tensor of type ",
+                    DataTypeString(DataTypeToEnum<Tin>::v()), " but got type ",
+                    DataTypeString(input_0.dtype())));
     const Tensor& input_1 = ctx->input(1);
+    OP_REQUIRES(ctx, input_1.dtype() == DataTypeToEnum<Tin>::v(),
+                errors::InvalidArgument(
+                    "Expected tensor of type ",
+                    DataTypeString(DataTypeToEnum<Tin>::v()), " but got type ",
+                    DataTypeString(input_1.dtype())));
     const Device& eigen_device = ctx->eigen_device<Device>();
     bool error = false;
     bool* const error_ptr = Functor::has_errors ? &error : nullptr;
 
     // NOTE: Handle three simple cases before building the BinaryOpState, which

Fixed code:     OP_REQUIRES(ctx, input_0.dtype() == DataTypeToEnum<Tin>::v(),
                errors::InvalidArgument(
                    "Expected tensor of type ",
                    DataTypeString(DataTypeToEnum<Tin>::v()), " but got type ",
                    DataTypeString(input_0.dtype())));
    OP_REQUIRES(ctx, input_1.dtype() == DataTypeToEnum<Tin>::v(),
                errors::InvalidArgument(
                    "Expected tensor of type ",
                    DataTypeString(DataTypeToEnum<Tin>::v()), " but got type ",
                    DataTypeString(input_1.dtype())));