CVE-2022-41900 (C++, published 2022-11-18T22:15Z)
Description: value: TensorFlow is an open source platform for machine learning. The security vulnerability results in FractionalMax(AVG)Pool with illegal pooling_ratio. Attackers using Tensorflow can exploit the vulnerability. They can access heap memory which is not in the control of user, leading to a crash or remote code execution. We have patched the issue in GitHub commit 216525144ee7c910296f5b05d214ca1327c9ce48. The fix will be included in TensorFlow 2.11.0. We will also cherry pick this commit on TensorFlow 2.10.1.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-787 \u2014 Out-of-bounds Write
The product writes data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
tensorflow/core/kernels/fractional_avg_pool_op.cc
tensorflow/core/kernels/fractional_max_pool_op.cc
tensorflow/core/ops/nn_ops.cc
tensorflow/core/ops/nn_ops_test.cc
tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py
tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py
Commit message: Fix security vulnerability with FractionalMax(AVG)Pool with illegal pooling_ratio

PiperOrigin-RevId: 483486453


Vulnerable code:
          context, pooling_ratio_[i] <= input_size[i],
          errors::InvalidArgument(
              "Pooling ratio cannot be bigger than input tensor dim size."));
    set_op(std::vector<float>{2.0f, 1, 1 / 1.5f, 1 / 2.0f});
    INFER_OK(op, "[10,20,30,40]", "[5,20,45,80];[20];[45]");
    INFER_OK(op, "[?,20,30,40]", "[?,20,45,80];[20];[45]");
    INFER_OK(op, "[10,?,30,40]", "[5,?,45,80];[?];[45]");
    INFER_OK(op, "[10,20,?,40]", "[5,20,?,80];[20];[?]");
    INFER_OK(op, "[10,20,30,?]", "[5,20,45,?];[20];[45]");
  def testPoolingRatio(self):

Fixed code:
    for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) {
      OP_REQUIRES(context, pooling_ratio_[i] >= 1,
                  errors::InvalidArgument(
                      "pooling_ratio cannot be smaller than 1, got: ",
                      pooling_ratio_[i]));
    }
          context, input_size[i] >= pooling_ratio_[i],
          errors::InvalidArgument("Pooling ratio is higher than input "
                                  "dimension size for dimension ",
                                  i, ". Input dim size: ", input_size[i],
                                  " pooling ratio: ", pooling_ratio_[i]));
    for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) {
      OP_REQUIRES(context, pooling_ratio_[i] >= 1,
                  errors::InvalidArgument(
                      "pooling_ratio cannot be smaller than 1, got: ",
                      pooling_ratio_[i]));
    }
  for (std::size_t i = 0; i < pooling_ratio.size(); ++i) {
    if (pooling_ratio[i] < 1) {
      return errors::InvalidArgument(
          "pooling_ratio cannot be smaller than 1, got: ", pooling_ratio[i]);
    }
  }

    // pooling_ratio must >= 1.0
    set_op(std::vector<float>{2.0f, 1, 1.5f, 4.0f});
    INFER_OK(op, "[10,20,30,40]", "[5,20,20,10];[20];[20]");
    INFER_OK(op, "[?,20,30,40]", "[?,20,20,10];[20];[20]");
    INFER_OK(op, "[10,?,30,40]", "[5,?,20,10];[?];[20]");
    INFER_OK(op, "[10,20,?,40]", "[5,20,?,10];[20];[?]");
    INFER_OK(op, "[10,20,30,?]", "[5,20,20,?];[20];[20]");
  def testPoolingRatioHasMoreDimThanInput(self):
    with self.cached_session() as _:
      with self.assertRaisesRegex(
          errors.InvalidArgumentError,
          r"Pooling ratio is higher than input dimension size for dimension 1.*"
      ):
        result = nn_ops.gen_nn_ops.fractional_avg_pool(
            value=constant_op.constant(
                value=[[[[1, 4, 2, 3]]]], dtype=dtypes.int64),
            pooling_ratio=[1.0, 1.44, 1.73, 1.0],
            pseudo_random=False,
            overlapping=False,
            deterministic=False,
            seed=0,
            seed2=0,
            name=None)
        self.evaluate(result)

  def testPoolingRatioValueOutOfRange(self):
    with self.cached_session() as _:
      # Whether turn on `TF2_BEHAVIOR` generates different error messages
      with self.assertRaisesRegex(
          (errors.InvalidArgumentError, ValueError),
          r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"):
        result = nn_ops.gen_nn_ops.fractional_avg_pool(
            value=np.zeros([3, 30, 30, 3]),
            pooling_ratio=[1, -1, 3, 1],
            pseudo_random=False,
            overlapping=False,
            deterministic=False,
            seed=0,
            seed2=0,
        )
        self.evaluate(result)

  def testPoolingRatioHasMoreDimThanInput(self):
  def testPoolingRatioValueOutOfRange(self):
    with self.cached_session() as _:
      # Whether turn on `TF2_BEHAVIOR` generates different error messages
      with self.assertRaisesRegex(
          (errors.InvalidArgumentError, ValueError),
          r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"):
        result = nn_ops.gen_nn_ops.fractional_max_pool(
            value=np.zeros([3, 30, 30, 3]),
            pooling_ratio=[1, -1, 3, 1],
            pseudo_random=False,
            overlapping=False,
            deterministic=False,
            seed=0,
            seed2=0,
        )
        self.evaluate(result)