CVE-2020-15193 (C++, published 2020-09-25T19:15Z)
Description: value: In Tensorflow before versions 2.2.1 and 2.3.1, the implementation of `dlpack.to_dlpack` can be made to use uninitialized memory resulting in further memory corruption. This is because the pybind11 glue code assumes that the argument is a tensor. However, there is nothing stopping users from passing in a Python object instead of a tensor. The uninitialized memory address is due to a `reinterpret_cast` Since the `PyObject` is a Python object, not a TensorFlow Tensor, the cast to `EagerTensor` fails. The issue is patched in commit 22e07fb204386768e5bcbea563641ea11f96ceb8 and is released in TensorFlow versions 2.2.1, or 2.3.1.
Severity: MEDIUM (CVSS v3 base score: 7.1)
Weakness: CWE-908 \u2014 Use of Uninitialized Resource
The product uses or accesses a resource that has not been initialized.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
tensorflow/c/eager/dlpack.cc
tensorflow/python/dlpack/BUILD
tensorflow/python/dlpack/dlpack_test.py
tensorflow/python/tfe_wrapper.cc
Commit message: Fix multiple vulnerabilities in `tf.experimental.dlpack.to_dlpack`.

We have a use after free caused by memory coruption, a segmentation fault caused by memory corruption, several memory leaks and an undefined behavior when taking the reference of a nullptr.

PiperOrigin-RevId: 332568894
Change-Id: Ife0fc05e103b35325094ae5d822ee5fdea764572


Vulnerable code:
  TensorReference tensor_ref(*tensor);  // This will call buf_->Ref()
  dlm_tensor->dl_tensor.ctx = GetDlContext(h, status);
  dlm_tensor->dl_tensor.data = TFE_TensorHandleDevicePointer(h, status);
  dlm_tensor->dl_tensor.dtype = GetDlDataType(data_type, status);
  dlm_tensor->dl_tensor.shape = &(*shape_arr)[0];
  dlm_tensor->dl_tensor.strides = &(*stride_arr)[0];
    tags = ["noasan"],  # TODO(b/159774807)
    TFE_TensorHandle* thandle = EagerTensor_Handle(eager_tensor_pyobject_ptr);

Fixed code:
  auto tf_dlm_context = GetDlContext(h, status);
  if (!status->status.ok()) {
    return nullptr;
  }

  auto* tf_dlm_data = TFE_TensorHandleDevicePointer(h, status);
  if (!status->status.ok()) {
    return nullptr;
  }

  auto tf_dlm_type = GetDlDataType(data_type, status);
  if (!status->status.ok()) {
    return nullptr;
  }

  TensorReference tensor_ref(*tensor);  // This will call buf_->Ref()
  dlm_tensor->dl_tensor.ctx = tf_dlm_context;
  dlm_tensor->dl_tensor.data = tf_dlm_data;
  dlm_tensor->dl_tensor.dtype = tf_dlm_type;
  dlm_tensor->dl_tensor.shape = shape_arr->data();
  dlm_tensor->dl_tensor.strides = stride_arr->data();


from tensorflow.python.framework import errors
  def testMustPassTensorArgumentToDLPack(self):
    with self.assertRaisesRegex(
        errors.InvalidArgumentError,
        "The argument to `to_dlpack` must be a TF tensor, not Python object"):
      dlpack.to_dlpack([1])


    if (!EagerTensor_CheckExact(eager_tensor_pyobject_ptr)) {
      status->status = tensorflow::errors::InvalidArgument(
          "The argument to `to_dlpack` must be a TF tensor, not Python object");
      tensorflow::MaybeRaiseRegisteredFromTFStatus(status.get());
    }

    TFE_TensorHandle* thandle = EagerTensor_Handle(eager_tensor_pyobject_ptr);