From 0f0003b81567f760ad223653463ad32561e60e25 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Fri, 10 Sep 2021 16:57:35 +0800 Subject: [PATCH] fix CVE-2020-26267 CVE-2021-29515 CVE-2021-29551 CVE-2021-37645 CVE-2021-37681 --- CVE-2020-26267-1.patch | 252 ++++++++++++++++++++++++++++++++++++++ CVE-2020-26267-2.patch | 266 +++++++++++++++++++++++++++++++++++++++++ CVE-2021-29515.patch | 41 +++++++ CVE-2021-29551.patch | 53 ++++++++ CVE-2021-37645.patch | 29 +++++ CVE-2021-37681-1.patch | 113 +++++++++++++++++ CVE-2021-37681-2.patch | 37 ++++++ tensorflow.spec | 12 +- 8 files changed, 802 insertions(+), 1 deletion(-) create mode 100644 CVE-2020-26267-1.patch create mode 100644 CVE-2020-26267-2.patch create mode 100644 CVE-2021-29515.patch create mode 100644 CVE-2021-29551.patch create mode 100644 CVE-2021-37645.patch create mode 100644 CVE-2021-37681-1.patch create mode 100644 CVE-2021-37681-2.patch diff --git a/CVE-2020-26267-1.patch b/CVE-2020-26267-1.patch new file mode 100644 index 0000000..1f4a16a --- /dev/null +++ b/CVE-2020-26267-1.patch @@ -0,0 +1,252 @@ +From 1a11d01c1fdd6683e9aa210dccde81de127dbf3e Mon Sep 17 00:00:00 2001 +From: Kaixi Hou +Date: Mon, 14 Sep 2020 15:52:22 -0700 +Subject: [PATCH 1/1] support reduce ops for 5d tensors in layout optimizer + +--- + .../generic_layout_optimizer_transposer.cc | 27 +++++++++- + tensorflow/core/kernels/data_format_ops.cc | 10 ++-- + tensorflow/core/kernels/data_format_ops.h | 53 ++++++++++++++----- + .../python/grappler/layout_optimizer_test.py | 39 ++++++++++++++ + tensorflow/python/ops/nn_test.py | 27 ++++++++++ + 5 files changed, 136 insertions(+), 20 deletions(-) + +diff --git a/tensorflow/core/grappler/optimizers/generic_layout_optimizer_transposer.cc b/tensorflow/core/grappler/optimizers/generic_layout_optimizer_transposer.cc +index ab7d8fcd..fbbeffc7 100644 +--- a/tensorflow/core/grappler/optimizers/generic_layout_optimizer_transposer.cc ++++ b/tensorflow/core/grappler/optimizers/generic_layout_optimizer_transposer.cc +@@ -1283,11 +1283,31 @@ bool ReduceTransposer::IsReduceAxisSupported( + Status ReduceTransposer::TransposeNode(TransposeContext* context, + utils::MutableNodeView* node) { + DCHECK(IsReduceOp(*node->node())); +- if (!ShouldProcess(*context, *node) || !IsFaninPortRankN(*node, 0, 4) || ++ const auto* output_shape_attr = node->GetAttr(kAttrOutputShape); ++ const auto& shape = output_shape_attr->list().shape(0); ++ const int rank = shape.dim_size(); ++ std::string src_format = context->src_format; ++ std::string dst_format = context->dst_format; ++ // Update the format from 4D to 5D layout if necessary. ++ if (rank == 5) { ++ std::string src_format_3d = src_format == "NHWC" ? "NDHWC" : "NCDHW"; ++ std::string dst_format_3d = dst_format == "NHWC" ? "NDHWC" : "NCDHW"; ++ context->AssignDeviceAndDataFormats(context->target_device, src_format_3d, ++ dst_format_3d); ++ } ++ if (!ShouldProcess(*context, *node) || !IsFaninPortRankN(*node, 0, rank) || + !IsReduceAxisSupported(*context, *node) || + !IsAfterDstToSrcTransform(*context, *node)) { ++ // Change back to the original layout due to early exit. ++ if (rank == 5) { ++ context->AssignDeviceAndDataFormats(context->target_device, src_format, ++ dst_format); ++ } + return Status::OK(); + } ++ VLOG(3) << "GenericLayoutOptimizer: transforming node '" << node->GetName() ++ << "' with op '" << node->GetOp() << "' from data format '" ++ << context->src_format << "' to '" << context->dst_format << "'"; + TF_RETURN_IF_ERROR(UpdateFaninEdgesWithOp(context, {0}, node, kOpTranspose)); + TF_RETURN_IF_ERROR( + UpdateFaninEdgesWithOp(context, {1}, node, kOpDataFormatDimMap)); +@@ -1295,6 +1315,11 @@ Status ReduceTransposer::TransposeNode(TransposeContext* context, + TF_RETURN_IF_ERROR( + UpdateFanoutEdgesWithOp(context, {0}, node, kOpTranspose)); + } ++ // Change back the format from 5D to 4D layout. ++ if (rank == 5) { ++ context->AssignDeviceAndDataFormats(context->target_device, src_format, ++ dst_format); ++ } + return context->graph_view->GetMutationBuilder()->Apply(); + } + +diff --git a/tensorflow/core/kernels/data_format_ops.cc b/tensorflow/core/kernels/data_format_ops.cc +index 181aa1b8..e9c71f17 100644 +--- a/tensorflow/core/kernels/data_format_ops.cc ++++ b/tensorflow/core/kernels/data_format_ops.cc +@@ -37,14 +37,14 @@ class DataFormatDimMapOp : public OpKernel { + OP_REQUIRES_OK(context, context->GetAttr("src_format", &src_format)); + string dst_format; + OP_REQUIRES_OK(context, context->GetAttr("dst_format", &dst_format)); +- OP_REQUIRES(context, src_format.size() == 4, ++ OP_REQUIRES(context, src_format.size() == 4 || src_format.size() == 5, + errors::InvalidArgument(strings::StrCat( +- "Source format must of length 4, received src_format = ", +- src_format))); ++ "Source format must of length 4 or 5, received " ++ "src_format = ", src_format))); + OP_REQUIRES( +- context, dst_format.size() == 4, ++ context, dst_format.size() == 4 || dst_format.size() == 5, + errors::InvalidArgument(strings::StrCat( +- "Destination format must of length 4, received dst_format = ", ++ "Destination format must of length 4 or 5, received dst_format = ", + dst_format))); + dst_idx_ = Tensor(DT_INT32, {static_cast(src_format.size())}); + for (int i = 0; i < src_format.size(); ++i) { +diff --git a/tensorflow/core/kernels/data_format_ops.h b/tensorflow/core/kernels/data_format_ops.h +index bc416fa7..89b54901 100644 +--- a/tensorflow/core/kernels/data_format_ops.h ++++ b/tensorflow/core/kernels/data_format_ops.h +@@ -28,24 +28,49 @@ template + struct DataFormatDimMap { + void operator()(const Device& d, typename TTypes::ConstFlat x, + typename TTypes::Flat y, const TTypes::Vec dst) { +- auto zero = x.constant(0); +- auto one = x.constant(1); +- auto two = x.constant(2); ++ if (dst.size() == 4) { ++ auto zero = x.constant(0); ++ auto one = x.constant(1); ++ auto two = x.constant(2); + +- auto f_zero = x.constant(dst(0)); +- auto f_one = x.constant(dst(1)); +- auto f_two = x.constant(dst(2)); +- auto f_three = x.constant(dst(3)); ++ auto f_zero = x.constant(dst(0)); ++ auto f_one = x.constant(dst(1)); ++ auto f_two = x.constant(dst(2)); ++ auto f_three = x.constant(dst(3)); + +- auto four = x.constant(4); +- auto x_mod = (x + four) % 4; ++ auto four = x.constant(4); ++ auto x_mod = (x + four) % 4; + +- auto is_zero = (x_mod == zero); +- auto is_one = (x_mod == one); +- auto is_two = (x_mod == two); ++ auto is_zero = (x_mod == zero); ++ auto is_one = (x_mod == one); ++ auto is_two = (x_mod == two); + +- y.device(d) = is_zero.select( +- f_zero, is_one.select(f_one, is_two.select(f_two, f_three))); ++ y.device(d) = is_zero.select( ++ f_zero, is_one.select(f_one, is_two.select(f_two, f_three))); ++ } else { ++ auto zero = x.constant(0); ++ auto one = x.constant(1); ++ auto two = x.constant(2); ++ auto three = x.constant(3); ++ ++ auto f_zero = x.constant(dst(0)); ++ auto f_one = x.constant(dst(1)); ++ auto f_two = x.constant(dst(2)); ++ auto f_three = x.constant(dst(3)); ++ auto f_four = x.constant(dst(4)); ++ ++ auto five = x.constant(5); ++ auto x_mod = (x + five) % 5; ++ ++ auto is_zero = (x_mod == zero); ++ auto is_one = (x_mod == one); ++ auto is_two = (x_mod == two); ++ auto is_three = (x_mod == three); ++ ++ y.device(d) = is_zero.select( ++ f_zero, is_one.select(f_one, is_two.select(f_two, ++ is_three.select(f_three, f_four)))); ++ } + } + }; + +diff --git a/tensorflow/python/grappler/layout_optimizer_test.py b/tensorflow/python/grappler/layout_optimizer_test.py +index 10f86980..f90da7ed 100644 +--- a/tensorflow/python/grappler/layout_optimizer_test.py ++++ b/tensorflow/python/grappler/layout_optimizer_test.py +@@ -215,6 +215,9 @@ class LayoutOptimizerTest(test.TestCase): + def _assert_map_nhwc_to_nchw(self, name, nodes): + self.assertIn(name + '-DimMapNHWCToNCHW-LayoutOptimizer', nodes) + ++ def _assert_map_ndhwc_to_ncdhw(self, name, nodes): ++ self.assertIn(name + '-DataFormatDimMapNDHWCToNCDHW-LayoutOptimizer', nodes) ++ + def _assert_vec_nchw_to_nhwc(self, name, nodes): + self.assertIn(name + '-VecPermuteNCHWToNHWC-LayoutOptimizer', nodes) + +@@ -286,6 +289,42 @@ class LayoutOptimizerTest(test.TestCase): + + self.assertAllClose(output_val_ref, output_val, atol=1e-3) + ++ @test_util.deprecated_graph_mode_only ++ def testReduceOpsFor5DTensors(self): ++ if test.is_gpu_available(cuda_only=True): ++ random_seed.set_random_seed(0) ++ x = random_ops.truncated_normal([1, 4, 2, 3, 3], seed=0) ++ w = random_ops.truncated_normal([2, 2, 2, 3, 3], seed=0) ++ gamma = random_ops.truncated_normal([1, 1, 1, 1, 3], seed=0) ++ beta = random_ops.truncated_normal([1, 1, 1, 1, 3], seed=0) ++ conv3d = gen_nn_ops.conv3d(x, w, [1, 1, 1, 1, 1], 'SAME') ++ y = math_ops.reduce_mean(conv3d, [0, 1, 2, 3], keepdims=True) ++ output = array_ops.identity(y) ++ ++ with session.Session(config=_get_config(False)) as sess: ++ output_val_ref = sess.run(output) ++ ++ with session.Session(config=_get_config()) as sess: ++ metadata = config_pb2.RunMetadata() ++ output_val = sess.run(output, run_metadata=metadata) ++ ++ nodes = [] ++ num_transposes = 0 ++ for node in metadata.cost_graph.node: ++ if _is_transpose(node.name): ++ num_transposes += 1 ++ nodes.append(node.name) ++ print(node.name) ++ ++ # The reduce op Mean needs to dim map the input reduce index to NCDHW. ++ # Then, the output needs to be tranposed back to NDHWC. ++ expected_num_transposes = 2 ++ self.assertEqual(expected_num_transposes, num_transposes) ++ self._assert_trans_ndhwc_to_ncdhw('Conv3D-0', nodes) ++ self._assert_map_ndhwc_to_ncdhw('Mean-1', nodes) ++ self._assert_trans_ncdhw_to_ndhwc('Mean-0-0', nodes) ++ self.assertAllClose(output_val_ref, output_val, atol=1e-3) ++ + @test_util.deprecated_graph_mode_only + def testSplitWithNonConstAxis(self): + if test.is_gpu_available(cuda_only=True): +diff --git a/tensorflow/python/ops/nn_test.py b/tensorflow/python/ops/nn_test.py +index bfe11b63..55d11a35 100644 +--- a/tensorflow/python/ops/nn_test.py ++++ b/tensorflow/python/ops/nn_test.py +@@ -1207,6 +1207,33 @@ class DataFormatDimMapTest(test_lib.TestCase): + y_val = self.evaluate(y) + self.assertAllEqual(y_val, y_val_expected) + ++ def testNDHWCtoNCDHW(self): ++ x_val = [1, -4, -3, -2] ++ y_val_expected = [2, 2, 3, 4] ++ x = constant_op.constant(x_val) ++ y = nn_ops.data_format_dim_map(x, src_format="NDHWC", dst_format="NCDHW") ++ with test_util.use_gpu(): ++ y_val = self.evaluate(y) ++ self.assertAllEqual(y_val, y_val_expected) ++ ++ def testNDHWCtoDHWNC(self): ++ x_val = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] ++ y_val_expected = [3, 0, 1, 2, 4, 3, 0, 1, 2, 4] ++ x = constant_op.constant(x_val) ++ y = nn_ops.data_format_dim_map(x, src_format="NDHWC", dst_format="DHWNC") ++ with test_util.use_gpu(): ++ y_val = self.evaluate(y) ++ self.assertAllEqual(y_val, y_val_expected) ++ ++ def testDNHWCtoWHDCN(self): ++ x_val = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] ++ y_val_expected = [4, 2, 1, 0, 3, 4, 2, 1, 0, 3] ++ x = constant_op.constant(x_val) ++ y = nn_ops.data_format_dim_map(x, src_format="NDHWC", dst_format="WHDCN") ++ with test_util.use_gpu(): ++ y_val = self.evaluate(y) ++ self.assertAllEqual(y_val, y_val_expected) ++ + def testArbitraryASCII(self): + x_val = [-4, -3, -2, -1, 0, 1, 2, 3] + y_val_expected = [3, 2, 1, 0, 3, 2, 1, 0] +-- +2.27.0 + diff --git a/CVE-2020-26267-2.patch b/CVE-2020-26267-2.patch new file mode 100644 index 0000000..9c03552 --- /dev/null +++ b/CVE-2020-26267-2.patch @@ -0,0 +1,266 @@ +From ebc70b7a592420d3d2f359e4b1694c236b82c7ae Mon Sep 17 00:00:00 2001 +From: Mihai Maruseac +Date: Mon, 7 Dec 2020 11:15:21 -0800 +Subject: [PATCH] Validate that `DataFormat*` attributes form a permutation. + +The `src_format` and `dst_format` attributes for the `DataFormatDimMap` and `DataFormatVecPermute` raw ops are supposed to determine a permutation. However, this was not validated and could result in unitialized memory accesses as well as writes outside of bounds and potential crashes. + +While here, we also test that the format attributes have the needed length, add tests for all validation failure cases, remove unnecessary calls to `strings::StrCat`, and fix a few grammar errors. + +This will be cherry-picked on the supported release branches. + +PiperOrigin-RevId: 346135579 +Change-Id: I1c76392382c89ad8f072d5bc93d70669851eb404 +--- + tensorflow/core/kernels/data_format_ops.cc | 72 ++++++++++++++-- + tensorflow/python/ops/nn_test.py | 96 ++++++++++++++++++++++ + 2 files changed, 161 insertions(+), 7 deletions(-) + +diff --git a/tensorflow/core/kernels/data_format_ops.cc b/tensorflow/core/kernels/data_format_ops.cc +index e9c71f17..abe2fbc3 100644 +--- a/tensorflow/core/kernels/data_format_ops.cc ++++ b/tensorflow/core/kernels/data_format_ops.cc +@@ -18,16 +18,52 @@ limitations under the License. + #define EIGEN_USE_THREADS + + #include "tensorflow/core/kernels/data_format_ops.h" ++ ++#include ++ + #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" + #include "tensorflow/core/framework/op_kernel.h" + #include "tensorflow/core/framework/register_types.h" + #include "tensorflow/core/framework/tensor.h" ++#include "tensorflow/core/platform/errors.h" + + namespace tensorflow { + + typedef Eigen::ThreadPoolDevice CPUDevice; + typedef Eigen::GpuDevice GPUDevice; + ++// Ensure that `src` and `dst` define a valid permutation. ++// Ops defined in this file assume that user specifies a permutation via two ++// string attributes. This check validates that these attributes properly define ++// it to prevent security vulnerabilities. ++static bool IsValidPermutation(const std::string& src, const std::string& dst) { ++ if (src.size() != dst.size()) { ++ return false; ++ } ++ ++ std::map characters; ++ ++ // Every character in `src` must be present only once ++ for (const auto c : src) { ++ if (characters[c]) { ++ return false; ++ } ++ characters[c] = true; ++ } ++ ++ // Every character in `dst` must show up in `src` exactly once ++ for (const auto c : dst) { ++ if (!characters[c]) { ++ return false; ++ } ++ characters[c] = false; ++ } ++ ++ // At this point, characters[] has been switched to true and false exactly ++ // once for all character in `src` (and `dst`) so we have a valid permutation ++ return true; ++} ++ + template + class DataFormatDimMapOp : public OpKernel { + public: +@@ -38,14 +74,18 @@ class DataFormatDimMapOp : public OpKernel { + string dst_format; + OP_REQUIRES_OK(context, context->GetAttr("dst_format", &dst_format)); + OP_REQUIRES(context, src_format.size() == 4 || src_format.size() == 5, +- errors::InvalidArgument(strings::StrCat( +- "Source format must of length 4 or 5, received " +- "src_format = ", src_format))); ++ errors::InvalidArgument( ++ "Source format must be of length 4 or 5, received " ++ "src_format = ", src_format)); ++ OP_REQUIRES(context, dst_format.size() == 4 || dst_format.size() == 5, ++ errors::InvalidArgument("Destination format must be of length " ++ "4 or 5, received dst_format = ", ++ dst_format)); + OP_REQUIRES( +- context, dst_format.size() == 4 || dst_format.size() == 5, +- errors::InvalidArgument(strings::StrCat( +- "Destination format must of length 4 or 5, received dst_format = ", +- dst_format))); ++ context, IsValidPermutation(src_format, dst_format), ++ errors::InvalidArgument( ++ "Destination and source format must determine a permutation, got ", ++ src_format, " and ", dst_format)); + dst_idx_ = Tensor(DT_INT32, {static_cast(src_format.size())}); + for (int i = 0; i < src_format.size(); ++i) { + for (int j = 0; j < dst_format.size(); ++j) { +@@ -77,8 +117,22 @@ class DataFormatVecPermuteOp : public OpKernel { + : OpKernel(context) { + string src_format; + OP_REQUIRES_OK(context, context->GetAttr("src_format", &src_format)); ++ OP_REQUIRES(context, src_format.size() == 4 || src_format.size() == 5, ++ errors::InvalidArgument( ++ "Source format must be of length 4 or 5, received " ++ "src_format = ", ++ src_format)); + string dst_format; + OP_REQUIRES_OK(context, context->GetAttr("dst_format", &dst_format)); ++ OP_REQUIRES(context, dst_format.size() == 4 || dst_format.size() == 5, ++ errors::InvalidArgument("Destination format must be of length " ++ "4 or 5, received dst_format = ", ++ dst_format)); ++ OP_REQUIRES( ++ context, IsValidPermutation(src_format, dst_format), ++ errors::InvalidArgument( ++ "Destination and source format must determine a permutation, got ", ++ src_format, " and ", dst_format)); + src_format_ = src_format; + dst_format_ = dst_format; + } +@@ -124,6 +178,10 @@ class DataFormatVecPermuteOp : public OpKernel { + }; + keep_only_spatial_dimensions(&src_format_str); + keep_only_spatial_dimensions(&dst_format_str); ++ OP_REQUIRES(context, ++ src_format_str.size() == 2 && dst_format_str.size() == 2, ++ errors::InvalidArgument( ++ "Format specifier must contain H and W for 2D case")); + } + ComputeDstIndex(src_format_str, dst_format_str, input.dims(), &dst_idx); + +diff --git a/tensorflow/python/ops/nn_test.py b/tensorflow/python/ops/nn_test.py +index 55d11a35..d2094a7d 100644 +--- a/tensorflow/python/ops/nn_test.py ++++ b/tensorflow/python/ops/nn_test.py +@@ -27,6 +27,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin + from tensorflow.python.eager import def_function + from tensorflow.python.framework import constant_op + from tensorflow.python.framework import dtypes ++from tensorflow.python.framework import errors + from tensorflow.python.framework import ops + from tensorflow.python.framework import tensor_spec + from tensorflow.python.framework import test_util +@@ -1234,6 +1235,7 @@ class DataFormatDimMapTest(test_lib.TestCase): + y_val = self.evaluate(y) + self.assertAllEqual(y_val, y_val_expected) + ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") + def testArbitraryASCII(self): + x_val = [-4, -3, -2, -1, 0, 1, 2, 3] + y_val_expected = [3, 2, 1, 0, 3, 2, 1, 0] +@@ -1243,6 +1245,46 @@ class DataFormatDimMapTest(test_lib.TestCase): + y_val = self.evaluate(y) + self.assertAllEqual(y_val, y_val_expected) + ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testInvalidLength(self): ++ x = [-4, -3, -2, -1, 0, 1, 2, 3] ++ with self.assertRaisesRegex(errors.InvalidArgumentError, ++ "Source format must be of length 4 or 5"): ++ op = nn_ops.data_format_dim_map( ++ x, src_format="12345678", dst_format="87654321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testDuplicateSrc(self): ++ x = [-4, -3, -2, -1, 0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_dim_map(x, src_format="1233", dst_format="4321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testDuplicateDst(self): ++ x = [-4, -3, -2, -1, 0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_dim_map(x, src_format="1234", dst_format="3321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testExtraSpecifiers(self): ++ x = [-4, -3, -2, -1, 0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_dim_map(x, src_format="1234", dst_format="5321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ + + class DataFormatVectorPermuteTest(test_lib.TestCase): + +@@ -1344,6 +1386,60 @@ class DataFormatVectorPermuteTest(test_lib.TestCase): + y_val = self.evaluate(y) + self.assertAllEqual(y_val, [[7, 4], [4, 5], [5, 1], [9, 3]]) + ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testInvalidLength(self): ++ x = [0, 1, 2, 3] ++ with self.assertRaisesRegex(errors.InvalidArgumentError, ++ "Source format must be of length 4 or 5"): ++ op = nn_ops.data_format_vec_permute( ++ x, src_format="12345678", dst_format="87654321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testDuplicateSrc(self): ++ x = [0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_vec_permute( ++ x, src_format="1233", dst_format="4321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testDuplicateDst(self): ++ x = [0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_vec_permute( ++ x, src_format="1234", dst_format="3321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def testExtraSpecifiers(self): ++ x = [0, 1, 2, 3] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Destination and source format must determine a permutation"): ++ op = nn_ops.data_format_vec_permute( ++ x, src_format="1234", dst_format="5321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ ++ @test_util.disable_xla("XLA catches the error and rethrows as different one") ++ def test2DNoWH(self): ++ x = [[0, 1], [2, 3]] ++ with self.assertRaisesRegex( ++ errors.InvalidArgumentError, ++ "Format specifier must contain H and W for 2D case"): ++ op = nn_ops.data_format_vec_permute( ++ x, src_format="1234", dst_format="4321") ++ with test_util.use_gpu(): ++ self.evaluate(op) ++ + + @test_util.run_all_in_graph_and_eager_modes + class AvgPoolTest(test_lib.TestCase): +-- +2.27.0 + diff --git a/CVE-2021-29515.patch b/CVE-2021-29515.patch new file mode 100644 index 0000000..713eaa8 --- /dev/null +++ b/CVE-2021-29515.patch @@ -0,0 +1,41 @@ +From a7116dd3913c4a4afd2a3a938573aa7c785fdfc6 Mon Sep 17 00:00:00 2001 +From: Mihai Maruseac +Date: Sat, 17 Apr 2021 20:55:53 -0700 +Subject: [PATCH] Validate `MatrixDiagV{2,3}` arguments to prevent breakage. + +PiperOrigin-RevId: 369056033 +Change-Id: Ic2018c297d3dd6f252dc1dd3667f1ed5cb1eaa42 +--- + .../core/kernels/matrix_diag_op.cc | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/tensorflow/core/kernels/matrix_diag_op.cc b/tensorflow/core/kernels/matrix_diag_op.cc +index 69cc8170793ae..d4eb589836a85 100644 +--- a/tensorflow/core/kernels/matrix_diag_op.cc ++++ b/tensorflow/core/kernels/matrix_diag_op.cc +@@ -192,9 +192,22 @@ class MatrixDiagOp : public OpKernel { + upper_diag_index = diag_index.flat()(1); + } + } +- num_rows = context->input(2).flat()(0); +- num_cols = context->input(3).flat()(0); +- padding_value = context->input(4).flat()(0); ++ ++ auto& num_rows_tensor = context->input(2); ++ OP_REQUIRES(context, TensorShapeUtils::IsScalar(num_rows_tensor.shape()), ++ errors::InvalidArgument("num_rows must be a scalar")); ++ num_rows = num_rows_tensor.flat()(0); ++ ++ auto& num_cols_tensor = context->input(3); ++ OP_REQUIRES(context, TensorShapeUtils::IsScalar(num_cols_tensor.shape()), ++ errors::InvalidArgument("num_cols must be a scalar")); ++ num_cols = num_cols_tensor.flat()(0); ++ ++ auto& padding_value_tensor = context->input(4); ++ OP_REQUIRES(context, ++ TensorShapeUtils::IsScalar(padding_value_tensor.shape()), ++ errors::InvalidArgument("padding_value must be a scalar")); ++ padding_value = padding_value_tensor.flat()(0); + } + + // Size validations. diff --git a/CVE-2021-29551.patch b/CVE-2021-29551.patch new file mode 100644 index 0000000..c057fb1 --- /dev/null +++ b/CVE-2021-29551.patch @@ -0,0 +1,53 @@ +From 480641e3599775a8895254ffbc0fc45621334f68 Mon Sep 17 00:00:00 2001 +From: Mihai Maruseac +Date: Sat, 24 Apr 2021 16:47:25 -0700 +Subject: [PATCH] Validate (and ensure validation sticks) inputs for + `MatrixTriangularSolve`. + +PiperOrigin-RevId: 370282444 +Change-Id: Iaed61a0b0727cc42c830658b72eb69f785f48dc5 +--- + .../matrix_triangular_solve_op_impl.h | 20 +++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/tensorflow/core/kernels/matrix_triangular_solve_op_impl.h b/tensorflow/core/kernels/matrix_triangular_solve_op_impl.h +index 99249f792b6ed..ce5392e62b9fa 100644 +--- a/tensorflow/core/kernels/matrix_triangular_solve_op_impl.h ++++ b/tensorflow/core/kernels/matrix_triangular_solve_op_impl.h +@@ -162,6 +162,9 @@ class BaseMatrixTriangularSolveOp : public OpKernel { + const Tensor& in1 = ctx->input(1); + + ValidateInputTensors(ctx, in0, in1); ++ if (!ctx->status().ok()) { ++ return; ++ } + + MatMulBCast bcast(in0.shape().dim_sizes(), in1.shape().dim_sizes()); + OP_REQUIRES( +@@ -230,13 +233,22 @@ class MatrixTriangularSolveOp + private: + void ValidateInputTensors(OpKernelContext* ctx, const Tensor& in0, + const Tensor& in1) override { ++ const auto in0_num_dims = in0.dims(); + OP_REQUIRES( +- ctx, in0.dims() >= 2, +- errors::InvalidArgument("In[0] ndims must be >= 2: ", in0.dims())); ++ ctx, in0_num_dims >= 2, ++ errors::InvalidArgument("In[0] ndims must be >= 2: ", in0_num_dims)); + ++ const auto in1_num_dims = in1.dims(); + OP_REQUIRES( +- ctx, in1.dims() >= 2, +- errors::InvalidArgument("In[0] ndims must be >= 2: ", in1.dims())); ++ ctx, in1_num_dims >= 2, ++ errors::InvalidArgument("In[1] ndims must be >= 2: ", in1_num_dims)); ++ ++ const auto in0_last_dim = in0.dim_size(in0_num_dims - 1); ++ const auto in0_prev_dim = in0.dim_size(in0_num_dims - 2); ++ OP_REQUIRES(ctx, in0_last_dim == in0_prev_dim, ++ errors::InvalidArgument( ++ "In[0] matrices in the last dimensions must be square (", ++ in0_last_dim, " =/= ", in0_prev_dim, ")")); + } + }; + diff --git a/CVE-2021-37645.patch b/CVE-2021-37645.patch new file mode 100644 index 0000000..3ab5b3e --- /dev/null +++ b/CVE-2021-37645.patch @@ -0,0 +1,29 @@ +From 96f364a1ca3009f98980021c4b32be5fdcca33a1 Mon Sep 17 00:00:00 2001 +From: Laura Pak +Date: Mon, 2 Aug 2021 13:27:01 -0700 +Subject: [PATCH] Validate axis input in tf.raw_ops.QuantizeAndDequantizeV4Grad + +PiperOrigin-RevId: 388291385 +Change-Id: I3bab68dc61d935afa96c0da021a7b722c6dc8dc8 +--- + tensorflow/core/kernels/quantize_and_dequantize_op.cc | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tensorflow/core/kernels/quantize_and_dequantize_op.cc b/tensorflow/core/kernels/quantize_and_dequantize_op.cc +index 540d900f9f869..d63a49a04be62 100644 +--- a/tensorflow/core/kernels/quantize_and_dequantize_op.cc ++++ b/tensorflow/core/kernels/quantize_and_dequantize_op.cc +@@ -158,6 +158,13 @@ class QuantizeAndDequantizeV4GradientOp : public OpKernel { + Tensor* input_backprop = nullptr; + OP_REQUIRES_OK(ctx, + ctx->allocate_output(0, input.shape(), &input_backprop)); ++ OP_REQUIRES( ++ ctx, axis_ >= -1, ++ errors::InvalidArgument("Axis must be at least -1. Found ", axis_)); ++ OP_REQUIRES(ctx, (axis_ == -1 || axis_ < input.shape().dims()), ++ errors::InvalidArgument( ++ "Axis should be -1 or 0 or a positive value less than ", ++ input.shape().dims(), "but given axis value was ", axis_)); + + OP_REQUIRES( + ctx, input.IsSameSize(gradient), diff --git a/CVE-2021-37681-1.patch b/CVE-2021-37681-1.patch new file mode 100644 index 0000000..18267d7 --- /dev/null +++ b/CVE-2021-37681-1.patch @@ -0,0 +1,113 @@ +From 9d94482224acde044692d74107339a29f862cbac Mon Sep 17 00:00:00 2001 +From: Advait Jain +Date: Wed, 15 Jul 2020 16:20:40 -0700 +Subject: [PATCH] Change some getters to not be inline. This enables some + +--- + tensorflow/lite/kernels/kernel_util.cc | 25 +++++++++++++ + tensorflow/lite/kernels/kernel_util.h | 49 +++++++++++--------------- + 2 files changed, 46 insertions(+), 28 deletions(-) + +diff --git a/tensorflow/lite/kernels/kernel_util.cc b/tensorflow/lite/kernels/kernel_util.cc +index 164aec3f..f7d7c25b 100644 +--- a/tensorflow/lite/kernels/kernel_util.cc ++++ b/tensorflow/lite/kernels/kernel_util.cc +@@ -27,6 +27,31 @@ limitations under the License. + #include "tensorflow/lite/kernels/internal/quantization_util.h" + + namespace tflite { ++const TfLiteTensor* GetInput(const TfLiteContext* context, ++ const TfLiteNode* node, int index) { ++ return &context->tensors[node->inputs->data[index]]; ++} ++ ++TfLiteTensor* GetVariableInput(TfLiteContext* context, const TfLiteNode* node, ++ int index) { ++ TfLiteTensor* tensor = &context->tensors[node->inputs->data[index]]; ++ return (tensor->is_variable) ? tensor : nullptr; ++} ++ ++TfLiteTensor* GetOutput(TfLiteContext* context, const TfLiteNode* node, ++ int index) { ++ return &context->tensors[node->outputs->data[index]]; ++} ++ ++const TfLiteTensor* GetOptionalInputTensor(const TfLiteContext* context, ++ const TfLiteNode* node, int index) { ++ const bool use_tensor = index < node->inputs->size && ++ node->inputs->data[index] != kTfLiteOptionalTensor; ++ if (use_tensor) { ++ return &context->tensors[node->inputs->data[index]]; ++ } ++ return nullptr; ++} + + // Per-axis + TfLiteStatus PopulateConvolutionQuantizationParams( +diff --git a/tensorflow/lite/kernels/kernel_util.h b/tensorflow/lite/kernels/kernel_util.h +index 59b1974c..371b712f 100644 +--- a/tensorflow/lite/kernels/kernel_util.h ++++ b/tensorflow/lite/kernels/kernel_util.h +@@ -24,38 +24,31 @@ limitations under the License. + + namespace tflite { + +-inline int NumDimensions(const TfLiteTensor* t) { return t->dims->size; } +-inline int SizeOfDimension(const TfLiteTensor* t, int dim) { +- return t->dims->data[dim]; +-} +-inline const TfLiteTensor* GetInput(const TfLiteContext* context, +- const TfLiteNode* node, int index) { +- const int tensor_index = node->inputs->data[index]; +- if (tensor_index < 0) { +- return nullptr; +- } +- return &context->tensors[tensor_index]; +-} ++// A fair number of functions in this header have historically been inline. ++// It is ok to change functions to not be inline if the latency with ++// benchmark_model for MobileNet + MobileBERT is unaffected. If such a change is ++// made, move the newly non-inlined function declarations to the top of this ++// header file. ++const TfLiteTensor* GetInput(const TfLiteContext* context, ++ const TfLiteNode* node, int index); ++ + // Note: You must check if result is not null: + // TfLiteTensor* my_tensor = GetVariableInput(context, node, kMyTensorIdx); + // TF_LITE_ENSURE(context, my_tensor != nullptr); +-inline TfLiteTensor* GetVariableInput(TfLiteContext* context, +- const TfLiteNode* node, int index) { +- const int tensor_index = node->inputs->data[index]; +- if (tensor_index < 0) { +- return nullptr; +- } +- TfLiteTensor* tensor = &context->tensors[tensor_index]; +- return (tensor->is_variable) ? tensor : nullptr; +-} +-inline TfLiteTensor* GetOutput(TfLiteContext* context, const TfLiteNode* node, +- int index) { +- const int tensor_index = node->outputs->data[index]; +- if (tensor_index < 0) { +- return nullptr; +- } +- return &context->tensors[tensor_index]; ++TfLiteTensor* GetVariableInput(TfLiteContext* context, const TfLiteNode* node, ++ int index); ++ ++TfLiteTensor* GetOutput(TfLiteContext* context, const TfLiteNode* node, ++ int index); ++ ++const TfLiteTensor* GetOptionalInputTensor(const TfLiteContext* context, ++ const TfLiteNode* node, int index); ++ ++inline int NumDimensions(const TfLiteTensor* t) { return t->dims->size; } ++inline int SizeOfDimension(const TfLiteTensor* t, int dim) { ++ return t->dims->data[dim]; + } ++ + inline TfLiteTensor* GetTemporary(TfLiteContext* context, + const TfLiteNode* node, int index) { + const int tensor_index = node->temporaries->data[index]; +-- +2.23.0 + diff --git a/CVE-2021-37681-2.patch b/CVE-2021-37681-2.patch new file mode 100644 index 0000000..9f95f62 --- /dev/null +++ b/CVE-2021-37681-2.patch @@ -0,0 +1,37 @@ +From 5b048e87e4e55990dae6b547add4dae59f4e1c76 Mon Sep 17 00:00:00 2001 +From: Mihai Maruseac +Date: Fri, 16 Jul 2021 09:14:31 -0700 +ubject: [PATCH] Fix a null pointer exception in SVDF + +--- + tensorflow/lite/kernels/kernel_util.cc | 1 + + tensorflow/lite/kernels/svdf.cc | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/tensorflow/lite/kernels/kernel_util.cc b/tensorflow/lite/kernels/kernel_util.cc +index f7d7c25b..f0074c09 100644 +--- a/tensorflow/lite/kernels/kernel_util.cc ++++ b/tensorflow/lite/kernels/kernel_util.cc +@@ -35,6 +35,7 @@ const TfLiteTensor* GetInput(const TfLiteContext* context, + TfLiteTensor* GetVariableInput(TfLiteContext* context, const TfLiteNode* node, + int index) { + TfLiteTensor* tensor = &context->tensors[node->inputs->data[index]]; ++ if (tensor == nullptr) return nullptr; + return (tensor->is_variable) ? tensor : nullptr; + } + +diff --git a/tensorflow/lite/kernels/svdf.cc b/tensorflow/lite/kernels/svdf.cc +index ec19fb92..863c18fd 100644 +--- a/tensorflow/lite/kernels/svdf.cc ++++ b/tensorflow/lite/kernels/svdf.cc +@@ -281,6 +281,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TfLiteTensor* scratch = GetTemporary(context, node, /*index=*/0); + + TfLiteTensor* state = GetVariableInput(context, node, kStateTensor); ++ TF_LITE_ENSURE(context, state != nullptr); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + switch (weights_feature->type) { +-- +2.23.0 + diff --git a/tensorflow.spec b/tensorflow.spec index ba78eb0..c0468a9 100644 --- a/tensorflow.spec +++ b/tensorflow.spec @@ -1,7 +1,7 @@ %global _empty_manifest_terminate_build 0 Name: tensorflow Version: 2.3.1 -Release: 9 +Release: 10 Summary: An Open Source Machine Learning Framework for Everyone License: Apache License 2.0 URL: https://www.tensorflow.org/ @@ -173,6 +173,13 @@ Patch0161: CVE-2021-29526-1.patch Patch0162: CVE-2021-29526-2.patch Patch0163: CVE-2021-29544-1.patch Patch0164: CVE-2021-29544-2.patch +Patch0165: CVE-2020-26267-1.patch +Patch0166: CVE-2020-26267-2.patch +Patch0167: CVE-2021-29515.patch +Patch0168: CVE-2021-29551.patch +Patch0169: CVE-2021-37645.patch +Patch0170: CVE-2021-37681-1.patch +Patch0171: CVE-2021-37681-2.patch Requires: python3-future Requires: python3-numpy @@ -219,6 +226,9 @@ bazel --output_user_root=`pwd`/../output_user_root build --host_copt=-Wno-string %{_bindir}/* %changelog +* Fri Sep 10 2021 yaoxin - 2.3.1-10 +- Fix CVE-2020-26267 CVE-2021-29515 CVE-2021-29551 CVE-2021-37645 CVE-2021-37681 + * Tue Aug 31 2021 yaoxin - 2.3.1-9 - Fix CVE-2020-15265 CVE-2020-15266 CVE-2021-37666 CVE-2021-29517 CVE-2021-29518 CVE-2021-29521 CVE-2021-29533 CVE-2021-29537 CVE-2021-29560 CVE-2021-29571 CVE-2021-29583 CVE-2021-29589 CVE-2021-29595 CVE-2021-29602 CVE-2021-29604 CVE-2021-29610-to-CVE-2021-29612 CVE-2021-29614 CVE-2021-29618 CVE-2021-37635 CVE-2021-37640 CVE-2021-37642 CVE-2021-37643 CVE-2021-37651 CVE-2021-37653-to-CVE-2021-37655 CVE-2021-37657 CVE-2021-37658 CVE-2021-37661 CVE-2021-37662 CVE-2021-37664 CVE-2021-37665 CVE-2021-37668 CVE-2021-37669 CVE-2021-37674 CVE-2021-37675 CVE-2021-37678 CVE-2021-37683 CVE-2021-37691 CVE-2021-29526 CVE-2021-29544 -- Gitee