Security fixes for CVE-2021-28876, CVE-2021-28878, CVE-2021-28879

This commit is contained in:
Josh Stone 2021-04-14 17:28:06 -07:00
parent 85a5f3ae28
commit 546915fc9c
4 changed files with 279 additions and 1 deletions

View File

@ -53,7 +53,7 @@
Name: rust
Version: 1.51.0
Release: 1%{?dist}
Release: 2%{?dist}
Summary: The Rust Programming Language
License: (ASL 2.0 or MIT) and (BSD and MIT)
# ^ written as: (rust itself) and (bundled libraries)
@ -71,6 +71,18 @@ Source0: https://static.rust-lang.org/dist/%{rustc_package}.tar.xz
# https://github.com/rust-lang/rust/issues/80810#issuecomment-781784032
Patch1: 0001-Revert-Auto-merge-of-79547.patch
# CVE-2021-28876 rust: panic safety issue in Zip implementation
# https://github.com/rust-lang/rust/pull/81741
Patch2: rustc-1.51.0-backport-pr81741.patch
# CVE-2021-28879 rust: integer overflow in the Zip implementation can lead to a buffer overflow
# https://github.com/rust-lang/rust/pull/82289
Patch3: rustc-1.51.0-backport-pr82289.patch
# CVE-2021-28878 rust: memory safety violation in Zip implementation when next_back() and next() are used together
# https://github.com/rust-lang/rust/pull/82292
Patch4: rustc-1.51.0-backport-pr82292.patch
### RHEL-specific patches below ###
# Disable cargo->libgit2->libssh2 on RHEL, as it's not approved for FIPS (rhbz1732949)
@ -405,6 +417,9 @@ test -f '%{local_rust_root}/bin/rustc'
%setup -q -n %{rustc_package}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%if %with disabled_libssh2
%patch100 -p1
@ -735,6 +750,9 @@ export %{rust_env}
%changelog
* Wed Apr 14 2021 Josh Stone <jistone@redhat.com> - 1.51.0-2
- Security fixes for CVE-2021-28876, CVE-2021-28878, CVE-2021-28879
* Thu Mar 25 2021 Josh Stone <jistone@redhat.com> - 1.51.0-1
- Update to 1.51.0.

View File

@ -0,0 +1,44 @@
From 40d3f2d7ef5835317fe9df9ecc01f4c363def4fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 4 Feb 2021 10:23:01 +0200
Subject: [PATCH] Increment `self.index` before calling
`Iterator::self.a.__iterator_get_unchecked` in `Zip` `TrustedRandomAccess`
specialization
Otherwise if `Iterator::self.a.__iterator_get_unchecked` panics the
index would not have been incremented yet and another call to
`Iterator::next` would read from the same index again, which is not
allowed according to the API contract of `TrustedRandomAccess` for
`!Clone`.
Fixes https://github.com/rust-lang/rust/issues/81740
(cherry picked from commit 86a4b27475aab52b998c15f5758540697cc9cff0)
---
library/core/src/iter/adapters/zip.rs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 98b8dca96140..9f9835345200 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -198,12 +198,13 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
} else if A::may_have_side_effect() && self.index < self.a.size() {
+ let i = self.index;
+ self.index += 1;
// match the base implementation's potential side effects
- // SAFETY: we just checked that `self.index` < `self.a.len()`
+ // SAFETY: we just checked that `i` < `self.a.len()`
unsafe {
- self.a.__iterator_get_unchecked(self.index);
+ self.a.__iterator_get_unchecked(i);
}
- self.index += 1;
None
} else {
None
--
2.31.1

View File

@ -0,0 +1,96 @@
From 5222e2ba2d97cd716a379b4ae6bc62c5f7c2dd36 Mon Sep 17 00:00:00 2001
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
Date: Fri, 19 Feb 2021 12:15:37 +0100
Subject: [PATCH 1/3] Increment self.len in specialized ZipImpl to avoid
underflow in size_hint
(cherry picked from commit 66a260617a88ed1ad55a46f03c5a90d5ad3004d3)
---
library/core/src/iter/adapters/zip.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 9f9835345200..f08bfac837fe 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -200,6 +200,7 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
} else if A::may_have_side_effect() && self.index < self.a.size() {
let i = self.index;
self.index += 1;
+ self.len += 1;
// match the base implementation's potential side effects
// SAFETY: we just checked that `i` < `self.a.len()`
unsafe {
--
2.31.1
From d39669fc8282830a374d19d204f7b4ee8eb1e381 Mon Sep 17 00:00:00 2001
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
Date: Fri, 19 Feb 2021 12:16:12 +0100
Subject: [PATCH 2/3] Add test for underflow in specialized Zip's size_hint
(cherry picked from commit 8b9ac4d4155c74db5b317046033ab9c05a09e351)
---
library/core/tests/iter/adapters/zip.rs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
index 1fce0951e365..a59771039295 100644
--- a/library/core/tests/iter/adapters/zip.rs
+++ b/library/core/tests/iter/adapters/zip.rs
@@ -245,3 +245,23 @@ fn test_double_ended_zip() {
assert_eq!(it.next_back(), Some((3, 3)));
assert_eq!(it.next(), None);
}
+
+#[test]
+fn test_issue_82282() {
+ fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
+ static UNIT_EMPTY_ARR: [(); 0] = [];
+
+ let mapped = arr.into_iter().map(|i| *i);
+ let mut zipped = mapped.zip(UNIT_EMPTY_ARR.iter());
+ zipped.next();
+ zipped
+ }
+
+ let arr = [1, 2, 3];
+ let zip = overflowed_zip(&arr).zip(overflowed_zip(&arr));
+
+ assert_eq!(zip.size_hint(), (0, Some(0)));
+ for _ in zip {
+ panic!();
+ }
+}
--
2.31.1
From 4b382167dd5ed5a6eac0cf314bfb86e3704b6e76 Mon Sep 17 00:00:00 2001
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
Date: Fri, 19 Feb 2021 12:17:48 +0100
Subject: [PATCH 3/3] Remove useless comparison since now self.index <=
self.len is an invariant
(cherry picked from commit aeb4ea739efb70e0002a4a9c4c7b8027dd0620b3)
---
library/core/src/iter/adapters/zip.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index f08bfac837fe..dcbcb1ce7200 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -261,7 +261,7 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
if sz_a != sz_b {
let sz_a = self.a.size();
if a_side_effect && sz_a > self.len {
- for _ in 0..sz_a - cmp::max(self.len, self.index) {
+ for _ in 0..sz_a - self.len {
self.a.next_back();
}
}
--
2.31.1

View File

@ -0,0 +1,120 @@
From 0babb88efc4d36f3defafc3c3c0343793fa05d52 Mon Sep 17 00:00:00 2001
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
Date: Wed, 3 Mar 2021 21:09:01 +0100
Subject: [PATCH 1/2] Prevent Zip specialization from calling
__iterator_get_unchecked twice with the same index after calling next_back
(cherry picked from commit 2371914a05f8f2763dffe6e2511d0870bcd6b461)
---
library/core/src/iter/adapters/zip.rs | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index dcbcb1ce7200..7dac0c63ca2d 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -13,9 +13,10 @@
pub struct Zip<A, B> {
a: A,
b: B,
- // index and len are only used by the specialized version of zip
+ // index, len and a_len are only used by the specialized version of zip
index: usize,
len: usize,
+ a_len: usize,
}
impl<A: Iterator, B: Iterator> Zip<A, B> {
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
@@ -110,6 +111,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
b,
index: 0, // unused
len: 0, // unused
+ a_len: 0, // unused
}
}
@@ -184,8 +186,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
B: TrustedRandomAccess + Iterator,
{
fn new(a: A, b: B) -> Self {
- let len = cmp::min(a.size(), b.size());
- Zip { a, b, index: 0, len }
+ let a_len = a.size();
+ let len = cmp::min(a_len, b.size());
+ Zip { a, b, index: 0, len, a_len }
}
#[inline]
@@ -197,7 +200,7 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
- } else if A::may_have_side_effect() && self.index < self.a.size() {
+ } else if A::may_have_side_effect() && self.index < self.a_len {
let i = self.index;
self.index += 1;
self.len += 1;
@@ -264,6 +267,7 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
for _ in 0..sz_a - self.len {
self.a.next_back();
}
+ self.a_len = self.len;
}
let sz_b = self.b.size();
if b_side_effect && sz_b > self.len {
@@ -275,6 +279,7 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
}
if self.index < self.len {
self.len -= 1;
+ self.a_len -= 1;
let i = self.len;
// SAFETY: `i` is smaller than the previous value of `self.len`,
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
--
2.31.1
From 19af66a6f3e2bbb4780bb9eae7eb53bd13e3dd0f Mon Sep 17 00:00:00 2001
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
Date: Fri, 19 Feb 2021 15:25:09 +0100
Subject: [PATCH 2/2] Add relevant test
(cherry picked from commit c1bfb9a78db6d481be1d03355672712c766e20b0)
---
library/core/tests/iter/adapters/zip.rs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
index a59771039295..000c15f72c88 100644
--- a/library/core/tests/iter/adapters/zip.rs
+++ b/library/core/tests/iter/adapters/zip.rs
@@ -265,3 +265,26 @@ fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
panic!();
}
}
+
+#[test]
+fn test_issue_82291() {
+ use std::cell::Cell;
+
+ let mut v1 = [()];
+ let v2 = [()];
+
+ let called = Cell::new(0);
+
+ let mut zip = v1
+ .iter_mut()
+ .map(|r| {
+ called.set(called.get() + 1);
+ r
+ })
+ .zip(&v2);
+
+ zip.next_back();
+ assert_eq!(called.get(), 1);
+ zip.next();
+ assert_eq!(called.get(), 1);
+}
--
2.31.1