VYPR
Low severityNVD Advisory· Published Jan 28, 2020· Updated Aug 4, 2024

Segmentation faultin TensorFlow when converting a Python string to tf.float16

CVE-2020-5215

Description

In TensorFlow before 1.15.2 and 2.0.1, converting a string (from Python) to a tf.float16 value results in a segmentation fault in eager mode as the format checks for this use case are only in the graph mode. This issue can lead to denial of service in inference/training where a malicious attacker can send a data point which contains a string instead of a tf.float16 value. Similar effects can be obtained by manipulating saved models and checkpoints whereby replacing a scalar tf.float16 value with a scalar string will trigger this issue due to automatic conversions. This can be easily reproduced by tf.constant("hello", tf.float16), if eager execution is enabled. This issue is patched in TensorFlow 1.15.1 and 2.0.1 with this vulnerability patched. TensorFlow 2.1.0 was released after we fixed the issue, thus it is not affected. Users are encouraged to switch to TensorFlow 1.15.1, 2.0.1 or 2.1.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
tensorflowPyPI
< 1.15.21.15.2
tensorflowPyPI
>= 2.0.0, < 2.0.12.0.1
tensorflow-cpuPyPI
< 1.15.21.15.2
tensorflow-cpuPyPI
>= 2.0.0, < 2.0.12.0.1
tensorflow-gpuPyPI
< 1.15.21.15.2
tensorflow-gpuPyPI
>= 2.0.0, < 2.0.12.0.1

Affected products

1

Patches

3
5d80e1e8e6ee

Merge pull request #36215 from tensorflow-jenkins/version-numbers-1.15.2-8214

https://github.com/tensorflow/tensorflowMihai MaruseacJan 26, 2020via osv
3 files changed · +3 3
  • tensorflow/core/public/version.h+1 1 modified
    @@ -22,7 +22,7 @@ limitations under the License.
     // tensorflow/tools/pip_package/setup.py
     #define TF_MAJOR_VERSION 1
     #define TF_MINOR_VERSION 15
    -#define TF_PATCH_VERSION 1
    +#define TF_PATCH_VERSION 2
     
     // TF_VERSION_SUFFIX is non-empty for pre-releases (e.g. "-alpha", "-alpha.1",
     // "-beta", "-rc", "-rc.1")
    
  • tensorflow/tensorflow.bzl+1 1 modified
    @@ -58,7 +58,7 @@ def register_extension_info(**kwargs):
     # not contain rc or alpha, only numbers.
     # Also update tensorflow/core/public/version.h
     # and tensorflow/tools/pip_package/setup.py
    -VERSION = "1.15.1"
    +VERSION = "1.15.2"
     VERSION_MAJOR = VERSION.split(".")[0]
     
     def if_v2(a):
    
  • tensorflow/tools/pip_package/setup.py+1 1 modified
    @@ -47,7 +47,7 @@
     # result for pip.
     # Also update tensorflow/tensorflow.bzl and
     # tensorflow/core/public/version.h
    -_VERSION = '1.15.1'
    +_VERSION = '1.15.2'
     
     REQUIRED_PACKAGES = [
         'absl-py >= 0.7.0',
    
765ac8d16eff

Merge pull request #35913 from tensorflow-jenkins/relnotes-2.0.1-6767

https://github.com/tensorflow/tensorflowMihai MaruseacJan 22, 2020via osv
1 file changed · +8 0
  • RELEASE.md+8 0 modified
    @@ -1,3 +1,11 @@
    +# Release 2.0.1
    +
    +## Bug Fixes and Other Changes
    +* Fixes a security vulnerability where converting a Python string to a `tf.float16` value produces a segmentation fault ([CVE-2020-5215](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-5215))
    +* Updates `curl` to `7.66.0` to handle [CVE-2019-5482](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5482) and [CVE-2019-5481](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5481)
    +* Updates `sqlite3` to `3.30.01` to handle [CVE-2019-19646](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-19646), [CVE-2019-19645](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-19645) and [CVE-2019-16168](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16168)
    +
    +
     # Release 2.0.0
     
     ## Major Features and Improvements
    
5ac1b9e24ff6

Fix segfault when attempting to convert string to float16.

https://github.com/tensorflow/tensorflowMihai MaruseacDec 20, 2019via ghsa
3 files changed · +95 12
  • tensorflow/python/BUILD+11 0 modified
    @@ -1839,6 +1839,17 @@ py_library(
         ],
     )
     
    +tf_py_test(
    +    name = "framework_constant_op_test",
    +    size = "small",
    +    srcs = ["framework/constant_op_test.py"],
    +    main = "framework/constant_op_test.py",
    +    python_version = "PY3",
    +    deps = [
    +        ":constant_op",
    +    ],
    +)
    +
     tf_py_test(
         name = "framework_registry_test",
         size = "small",
    
  • tensorflow/python/framework/constant_op_test.py+61 0 added
    @@ -0,0 +1,61 @@
    +# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
    +#
    +# Licensed under the Apache License, Version 2.0 (the "License");
    +# you may not use this file except in compliance with the License.
    +# You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +# ==============================================================================
    +"""Tests for tensorflow.python.framework.constant_op."""
    +
    +from __future__ import absolute_import
    +from __future__ import division
    +from __future__ import print_function
    +
    +from absl.testing import parameterized
    +
    +from tensorflow.python.framework import constant_op
    +from tensorflow.python.framework import dtypes
    +from tensorflow.python.framework import ops
    +from tensorflow.python.platform import test
    +
    +
    +class ConstantOpTest(test.TestCase, parameterized.TestCase):
    +
    +  @parameterized.parameters(
    +      dtypes.bfloat16,
    +      dtypes.complex128,
    +      dtypes.complex64,
    +      dtypes.double,
    +      dtypes.float16,
    +      dtypes.float32,
    +      dtypes.float64,
    +      dtypes.half,
    +      dtypes.int16,
    +      dtypes.int32,
    +      dtypes.int64,
    +      dtypes.int8,
    +      dtypes.qint16,
    +      dtypes.qint32,
    +      dtypes.qint8,
    +      dtypes.quint16,
    +      dtypes.quint8,
    +      dtypes.uint16,
    +      dtypes.uint32,
    +      dtypes.uint64,
    +      dtypes.uint8,
    +  )
    +  def test_convert_string_to_number(self, dtype):
    +    with self.assertRaises(TypeError):
    +      constant_op.constant("hello", dtype)
    +
    +
    +if __name__ == "__main__":
    +  ops.enable_eager_execution()
    +  test.main()
    
  • tensorflow/python/lib/core/py_seq_tensor.cc+23 12 modified
    @@ -21,6 +21,7 @@ limitations under the License.
     #include "tensorflow/core/lib/core/errors.h"
     #include "tensorflow/core/lib/core/stringpiece.h"
     #include "tensorflow/core/lib/strings/str_util.h"
    +#include "tensorflow/core/platform/macros.h"
     #include "tensorflow/core/platform/types.h"
     #include "tensorflow/python/lib/core/numpy.h"
     #include "tensorflow/python/lib/core/py_util.h"
    @@ -396,6 +397,21 @@ typedef Converter<int32> Int32Converter;
     
     // Floating-point support
     
    +// Returns `true` if `out` overflows when converted from `as_double`.
    +template <class T>
    +static inline bool CheckForOverflow(double as_double, T* out) {
    +  return (sizeof(T) < sizeof(double) && std::isinf(*out) &&
    +          std::isfinite(as_double));
    +}
    +
    +// There is no `std::isinf` that takes `Eigen::half` as argument but Eigen
    +// provides `Eigen::half_impl::isinf` instead.
    +template <>
    +inline bool CheckForOverflow<Eigen::half>(double as_double, Eigen::half* out) {
    +  return (sizeof(Eigen::half) < sizeof(double) &&
    +          Eigen::half_impl::isinf(*out) && std::isfinite(as_double));
    +}
    +
     template <class T>
     static const char* ConvertOneFloat(PyObject* v, T* out) {
       if (PyErr_Occurred()) {
    @@ -405,20 +421,19 @@ static const char* ConvertOneFloat(PyObject* v, T* out) {
         const double as_double = PyFloat_AS_DOUBLE(v);
         *out = static_cast<T>(as_double);
         // Check for overflow
    -    if (TF_PREDICT_FALSE(sizeof(T) < sizeof(double) && std::isinf(*out) &&
    -                         std::isfinite(as_double))) {
    +    if (TF_PREDICT_FALSE(CheckForOverflow<T>(as_double, out))) {
           return ErrorOutOfRangeDouble;
         }
         return nullptr;
       }
     #if PY_MAJOR_VERSION < 3
       if (PyInt_Check(v)) {
    -    *out = PyInt_AS_LONG(v);
    +    *out = static_cast<T>(PyInt_AS_LONG(v));
         return nullptr;
       }
     #endif
       if (PyLong_Check(v)) {
    -    *out = PyLong_AsDouble(v);
    +    *out = static_cast<T>(PyLong_AsDouble(v));
         if (PyErr_Occurred()) return ErrorOutOfRangeDouble;
         return nullptr;
       }
    @@ -467,13 +482,7 @@ struct ConverterTraits<Eigen::half> {
       static const tensorflow::DataType kTypeEnum = DT_HALF;
     
       static const char* ConvertScalar(PyObject* v, Eigen::half* out) {
    -    // NOTE(nareshmodi): Is there a way to convert to C double without the
    -    // intermediate Python double? This will help with ConvertOneFloat as well.
    -    Safe_PyObjectPtr as_float = make_safe(PyNumber_Float(v));
    -    double v_double = PyFloat_AS_DOUBLE(as_float.get());
    -    *out = Eigen::half(v_double);
    -
    -    return nullptr;
    +    return ConvertOneFloat<Eigen::half>(v, out);
       }
     };
     
    @@ -613,7 +622,9 @@ Status PySeqToTensor(PyObject* obj, DataType dtype, Tensor* ret) {
           break;
     
         case DT_HALF:
    -      RETURN_STRING_AS_STATUS(NumpyHalfConverter::Convert(obj, &state, ret));
    +      if (NumpyHalfConverter::Convert(obj, &state, ret) == nullptr)
    +        return Status::OK();
    +      break;
     
         case DT_INT64:
           if (Int64Converter::Convert(obj, &state, ret) == nullptr)
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

9

News mentions

0

No linked articles in our index yet.