diff --git a/CVE-2021-41210.patch b/CVE-2021-41210.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3baaaffdb8f618f1e893d8b9acc4691409e9be1 --- /dev/null +++ b/CVE-2021-41210.patch @@ -0,0 +1,57 @@ +From 701cfaca222a82afbeeb17496bd718baa65a67d2 Mon Sep 17 00:00:00 2001 +From: Robert Neale +Date: Tue, 26 Oct 2021 16:50:02 -0700 +Subject: [PATCH] Fix heap out of bounds error in + tf.raw_ops.SparseCountSparseOutput shape inference when it is called with + invalid inputs, and add a test for it. + +PiperOrigin-RevId: 405766415 +Change-Id: I77d244ef35f351ef7b6f821efd959cac2c66db24 +--- + tensorflow/core/ops/count_ops.cc | 2 ++ + tensorflow/python/ops/bincount_ops_test.py | 19 +++++++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/tensorflow/core/ops/count_ops.cc b/tensorflow/core/ops/count_ops.cc +index 4f9631310df92..aa6c0437337af 100644 +--- a/tensorflow/core/ops/count_ops.cc ++++ b/tensorflow/core/ops/count_ops.cc +@@ -41,6 +41,8 @@ Status DenseCountSparseOutputShapeFn(InferenceContext *c) { + } + + Status SparseCountSparseOutputShapeFn(InferenceContext *c) { ++ ShapeHandle unused; ++ TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 2, &unused)); + auto rank = c->Dim(c->input(0), 1); + auto nvals = c->UnknownDim(); + c->set_output(0, c->Matrix(nvals, rank)); // out.indices +diff --git a/tensorflow/python/ops/bincount_ops_test.py b/tensorflow/python/ops/bincount_ops_test.py +index 3c7a2a5da9daf..de7d1423870d7 100644 +--- a/tensorflow/python/ops/bincount_ops_test.py ++++ b/tensorflow/python/ops/bincount_ops_test.py +@@ -831,6 +831,25 @@ def test_ragged_input_different_shape_fails(self): + self.evaluate(bincount_ops.sparse_bincount(x, weights=weights, axis=-1)) + + ++class RawOpsHeapOobTest(test.TestCase, parameterized.TestCase): ++ ++ @test_util.run_v1_only("Test security error") ++ def testSparseCountSparseOutputBadIndicesShapeTooSmall(self): ++ indices = [1] ++ values = [[1]] ++ weights = [] ++ dense_shape = [10] ++ with self.assertRaisesRegex(ValueError, ++ "Shape must be rank 2 but is rank 1 for"): ++ self.evaluate( ++ gen_count_ops.SparseCountSparseOutput( ++ indices=indices, ++ values=values, ++ dense_shape=dense_shape, ++ weights=weights, ++ binary_output=True)) ++ ++ + @test_util.run_all_in_graph_and_eager_modes + @test_util.disable_tfrt + class RawOpsTest(test.TestCase, parameterized.TestCase): diff --git a/CVE-2021-41219.patch b/CVE-2021-41219.patch new file mode 100644 index 0000000000000000000000000000000000000000..89169253efb9785fa2fbcfd19e3894efb99f7ae5 --- /dev/null +++ b/CVE-2021-41219.patch @@ -0,0 +1,43 @@ +From e6cf28c72ba2eb949ca950d834dd6d66bb01cfae Mon Sep 17 00:00:00 2001 +From: Penporn Koanantakool +Date: Tue, 5 Oct 2021 21:54:15 -0700 +Subject: [PATCH] Validate that matrix dimension sizes in SparseMatMul are + positive. + +PiperOrigin-RevId: 401149683 +Change-Id: Ib33eafc561a39c8741ece80b2edce6d4aae9a57d +--- + tensorflow/core/kernels/sparse_matmul_op.cc | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/tensorflow/core/kernels/sparse_matmul_op.cc b/tensorflow/core/kernels/sparse_matmul_op.cc +index a02afafa33e3a..6bf9dfa3d8bb7 100644 +--- a/tensorflow/core/kernels/sparse_matmul_op.cc ++++ b/tensorflow/core/kernels/sparse_matmul_op.cc +@@ -32,6 +32,7 @@ limitations under the License. + #include "tensorflow/core/kernels/fill_functor.h" + #include "tensorflow/core/lib/core/blocking_counter.h" + #include "tensorflow/core/lib/core/threadpool.h" ++#include "tensorflow/core/platform/errors.h" + #include "tensorflow/core/platform/logging.h" + #include "tensorflow/core/platform/macros.h" + #include "tensorflow/core/platform/mutex.h" +@@ -980,9 +981,18 @@ class SparseMatMulOp : public OpKernel { + errors::InvalidArgument( + "Matrix size incompatible: a: ", a.shape().DebugString(), + ", b: ", b.shape().DebugString())); ++ OP_REQUIRES(ctx, m >= 0 && n >= 0 && k >= 0, ++ errors::InvalidArgument( ++ "Matrix dimensions cannot be negative: a: ", ++ a.shape().DebugString(), ", b: ", b.shape().DebugString())); + Tensor* output = nullptr; + OP_REQUIRES_OK(ctx, ctx->allocate_output(0, TensorShape({m, n}), &output)); + ++ // Return early if at least one of the output dimension size is 0. ++ if (m == 0 || n == 0) { ++ return; ++ } ++ + if (k == 0) { + // If the inner dimension k in the matrix multiplication is zero, we fill + // the output with zeros. diff --git a/CVE-2021-41223.patch b/CVE-2021-41223.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe01d34c049502079b7396534d922457d83c6f2a --- /dev/null +++ b/CVE-2021-41223.patch @@ -0,0 +1,218 @@ +From aab9998916c2ffbd8f0592059fad352622f89cda Mon Sep 17 00:00:00 2001 +From: Reed Wanderman-Milne +Date: Wed, 29 Sep 2021 13:00:50 -0700 +Subject: [PATCH] Add shape checks to FusedBatchNorm kernels. + +--- + .../core/kernels/fused_batch_norm_op.cc | 38 +++++- + .../python/ops/nn_fused_batchnorm_test.py | 122 ++++++++++++++++++ + 2 files changed, 153 insertions(+), 7 deletions(-) + +diff --git a/tensorflow/core/kernels/fused_batch_norm_op.cc b/tensorflow/core/kernels/fused_batch_norm_op.cc +index bd5dab36..b19323f0 100644 +--- a/tensorflow/core/kernels/fused_batch_norm_op.cc ++++ b/tensorflow/core/kernels/fused_batch_norm_op.cc +@@ -1279,18 +1279,20 @@ class FusedBatchNormOpBase : public OpKernel { + errors::InvalidArgument("offset must have the same number of elements " + "as the channels of x, got ", + offset.NumElements(), " and ", num_channels)); +- if (estimated_mean.NumElements() != 0) { ++ if (!is_training_ || exponential_avg_factor_ != 1.) { ++ std::string prefix_msg = is_training_ ? "When exponential_avg_factor != 1" ++ : "When is_training=false"; + OP_REQUIRES(context, estimated_mean.NumElements() == num_channels, + errors::InvalidArgument( +- "mean must be empty or have the same number of " +- "elements as the channels of x, got ", ++ prefix_msg, ++ ", mean must have the same number " ++ "of elements as the channels of x, got ", + estimated_mean.NumElements(), " and ",num_channels)); +- } +- if (estimated_variance.NumElements() != 0) { + OP_REQUIRES(context, estimated_variance.NumElements() == num_channels, + errors::InvalidArgument( +- "variance must be empty or have the same number of " +- "elements as the channels of x, got ", ++ prefix_msg, ++ ", variance must have the same " ++ "number of elements as the channels of x, got ", + estimated_variance.NumElements(), " and ", num_channels)); + } + +@@ -1434,6 +1436,28 @@ class FusedBatchNormGradOpBase : public OpKernel { + errors::InvalidArgument( + "saved variance must be 1-dimensional", + saved_maybe_inv_var_or_pop_var.shape().DebugString())); ++ OP_REQUIRES( ++ context, x.shape() == y_backprop.shape(), ++ errors::InvalidArgument( ++ "x and y_backprop must have same shape, but x has shape ", ++ x.shape(), " and y_backprop has shape ", y_backprop.shape())); ++ ++ const auto num_channels = GetTensorDim(x, tensor_format_, 'C'); ++ OP_REQUIRES( ++ context, scale.NumElements() == num_channels, ++ errors::InvalidArgument("scale must have the same number of elements " ++ "as the channels of x, got ", ++ scale.NumElements(), " and ", num_channels)); ++ OP_REQUIRES( ++ context, saved_mean_or_pop_mean.NumElements() == num_channels, ++ errors::InvalidArgument("reserve_space_1 must have the same number of " ++ "elements as the channels of x, got ", ++ scale.NumElements(), " and ", num_channels)); ++ OP_REQUIRES( ++ context, saved_maybe_inv_var_or_pop_var.NumElements() == num_channels, ++ errors::InvalidArgument("reserve_space_2 must have the same number of " ++ "elements as the channels of x, got ", ++ scale.NumElements(), " and ", num_channels)); + + Tensor* x_backprop = nullptr; + OP_REQUIRES_OK(context, +diff --git a/tensorflow/python/ops/nn_fused_batchnorm_test.py b/tensorflow/python/ops/nn_fused_batchnorm_test.py +index 1742a919..8fecd1c7 100644 +--- a/tensorflow/python/ops/nn_fused_batchnorm_test.py ++++ b/tensorflow/python/ops/nn_fused_batchnorm_test.py +@@ -20,10 +20,13 @@ from __future__ import print_function + + import numpy as np + ++from tensorflow.python.eager import context + from tensorflow.python.framework import constant_op + from tensorflow.python.framework import dtypes ++from tensorflow.python.framework import errors_impl + from tensorflow.python.framework import test_util + from tensorflow.python.ops import array_ops ++from tensorflow.python.ops import gen_nn_ops + from tensorflow.python.ops import gradient_checker + from tensorflow.python.ops import gradients_impl + from tensorflow.python.ops import math_ops +@@ -610,6 +613,125 @@ class BatchNormalizationTest(test.TestCase): + } + self._testBatchNormGradGrad(config) + ++ def testEagerShapeErrors(self): ++ with context.eager_mode(): ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((3,)) ++ offset = array_ops.ones((2,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'scale must have the same number of elements'): ++ nn_impl.fused_batch_norm(x, scale, offset) ++ ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ offset = array_ops.ones((3,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'offset must have the same number of elements'): ++ nn_impl.fused_batch_norm(x, scale, offset) ++ ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ offset = array_ops.ones((2,)) ++ mean = array_ops.ones((0,)) ++ variance = array_ops.ones((2,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'When is_training=false, mean must have the same number of elements'): ++ nn_impl.fused_batch_norm( ++ x, scale, offset, mean=mean, variance=variance, is_training=False) ++ ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ offset = array_ops.ones((2,)) ++ mean = array_ops.ones((2,)) ++ variance = array_ops.ones((0,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'When is_training=false, variance must have the same number of ' ++ nn_impl.fused_batch_norm( ++ x, scale, offset, mean=mean, variance=variance, is_training=False) ++ ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ offset = array_ops.ones((2,)) ++ mean = array_ops.ones((0,)) ++ variance = array_ops.ones((2,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'When exponential_avg_factor != 1, mean must have the same number of ' ++ 'elements'): ++ nn_impl.fused_batch_norm( ++ x, ++ scale, ++ offset, ++ mean=mean, ++ variance=variance, ++ exponential_avg_factor=0.5) ++ ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ offset = array_ops.ones((2,)) ++ mean = array_ops.ones((2,)) ++ variance = array_ops.ones((0,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'When exponential_avg_factor != 1, variance must have the same ' ++ 'number of elements'): ++ nn_impl.fused_batch_norm( ++ x, ++ scale, ++ offset, ++ mean=mean, ++ variance=variance, ++ exponential_avg_factor=0.5) ++ ++ def testEagerShapeGradErrors(self): ++ with context.eager_mode(): ++ y_backprop = array_ops.ones((2, 2, 2, 3)) ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ reserve_space_1 = array_ops.ones((2,)) ++ reserve_space_2 = array_ops.ones((2,)) ++ with self.assertRaisesRegex(errors_impl.InvalidArgumentError, ++ 'x and y_backprop must have same shape,'): ++ gen_nn_ops.fused_batch_norm_grad_v2(y_backprop, x, scale, ++ reserve_space_1, reserve_space_2) ++ ++ y_backprop = array_ops.ones((2, 2, 2, 2)) ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((3,)) ++ reserve_space_1 = array_ops.ones((2,)) ++ reserve_space_2 = array_ops.ones((2,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'scale must have the same number of elements'): ++ gen_nn_ops.fused_batch_norm_grad_v2(y_backprop, x, scale, ++ reserve_space_1, reserve_space_2) ++ ++ y_backprop = array_ops.ones((2, 2, 2, 2)) ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ reserve_space_1 = array_ops.ones((3,)) ++ reserve_space_2 = array_ops.ones((2,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'reserve_space_1 must have the same number of elements'): ++ gen_nn_ops.fused_batch_norm_grad_v2(y_backprop, x, scale, ++ reserve_space_1, reserve_space_2) ++ ++ y_backprop = array_ops.ones((2, 2, 2, 2)) ++ x = array_ops.ones((2, 2, 2, 2)) ++ scale = array_ops.ones((2,)) ++ reserve_space_1 = array_ops.ones((2,)) ++ reserve_space_2 = array_ops.ones((3,)) ++ with self.assertRaisesRegex( ++ errors_impl.InvalidArgumentError, ++ 'reserve_space_2 must have the same number of elements'): ++ gen_nn_ops.fused_batch_norm_grad_v2(y_backprop, x, scale, ++ reserve_space_1, reserve_space_2) ++ + + if __name__ == '__main__': + test.main() +-- +2.23.0 + diff --git a/tensorflow.spec b/tensorflow.spec index 934902720debe3269275aae2233ba8017a7d1144..49af647ddde8852ff24b149afa3c8592426d0163 100644 --- a/tensorflow.spec +++ b/tensorflow.spec @@ -1,7 +1,7 @@ %global _empty_manifest_terminate_build 0 Name: tensorflow Version: 2.3.1 -Release: 11 +Release: 12 Summary: An Open Source Machine Learning Framework for Everyone License: Apache License 2.0 URL: https://www.tensorflow.org/ @@ -188,6 +188,9 @@ Patch0176: CVE-2021-37679.patch Patch0177: CVE-2021-37690-1.patch Patch0178: CVE-2021-37690-2.patch Patch0179: CVE-2021-37690-3.patch +Patch0180: CVE-2021-41210.patch +Patch0181: CVE-2021-41219.patch +Patch0182: CVE-2021-41223.patch Requires: python3-future Requires: python3-numpy @@ -256,6 +259,9 @@ echo "%{_libdir}/openmpi/lib" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.c %changelog +* Wed Nov 10 2021 houyingchao - 2.3.1-12 +- Fix CVE-2021-41210 CVE-2021-41219 CVE-2021-41223 + * Fri Sep 17 2021 yaoxin - 2.3.1-11 - Fix CVE-2021-37690