Commit f1f68e2e authored by Ariadne Conill's avatar Ariadne Conill
Browse files

community/rust: add mitigations for CVE-2020-36323 and CVE-2021-31162

parent e964ab36
......@@ -8,7 +8,7 @@ pkgname=rust
pkgver=1.51.0
_llvmver=11
_bootver=1.50.0
pkgrel=1
pkgrel=2
pkgdesc="The Rust Programming Language"
url="https://www.rust-lang.org"
arch="x86_64 armv7 armhf aarch64 x86 ppc64le"
......@@ -79,10 +79,15 @@ source="https://static.rust-lang.org/dist/rustc-$pkgver-src.tar.gz
0006-Prefer-libgcc_eh-over-libunwind-for-musl.patch
0007-do-not-install-libunwind-source.patch
mips-softfloat.patch
CVE-2020-36323.patch
CVE-2021-31162.patch
"
builddir="$srcdir/rustc-$pkgver-src"
# secfixes:
# 1.51.0-r2:
# - CVE-2020-36323
# - CVE-2021-31162
# 1.34.2-r0:
# - CVE-2019-12083
# 1.26.0-r0:
......@@ -352,4 +357,6 @@ c31fdfe8a9b3411576c75da46645cf0465b9053000a2ab49cf9b2f2733f679d6d33acbf236d67a20
d5d3ccc5c3a73bf1816106ba00805346ea28f2e6337d960e9e9f776ba59d22abd8864382f163d32dd9a278df38c080949dafc70169728f44080ddc04f1e7f125 link-musl-dynamically.patch
fa67468667903290b8e6d16d6777f80aac49d987e8e60c43f8302da77fa1e0e35c4d363d216867c79989c8c35d552c0d5dd6bce69734ed0ce75b4b67ca924953 0006-Prefer-libgcc_eh-over-libunwind-for-musl.patch
7af23c34096f7a03c5a1b40aa07e00dd6193743c872881018a9baa900f240c6e44918e481ab5ed7787a70ef361e4aeec2a7719bcd695f52988262e23271b44e5 0007-do-not-install-libunwind-source.patch
4cb2592d30cd1a776375522631aa284dd077eaa39b109921d6ee5906fd0130b048e07d3adef1d7221f5c001d1df5187feb3e3687e0aa5d19279099065a7d4cb7 mips-softfloat.patch"
4cb2592d30cd1a776375522631aa284dd077eaa39b109921d6ee5906fd0130b048e07d3adef1d7221f5c001d1df5187feb3e3687e0aa5d19279099065a7d4cb7 mips-softfloat.patch
6e12429f9f6fb9d830acdd0e4b07cf676aa5752afbbffd8a055442c871982e342bce0febe1e13a6c0df13bba291c82e33e91ff3c91854d48edb1bd0a3a91fefa CVE-2020-36323.patch
61bd593ac3e3e309eb8f56c2e25d92e8db68cf2da5452b3883d877205b0000c2f2d3943a425449350bf21f595d3f6c6717ce477720628c8bfbf95c26e428aef0 CVE-2021-31162.patch"
From 6d43225bfb08ec91f7476b76c7fec632c4a096ef Mon Sep 17 00:00:00 2001
From: Yechan Bae <yechan@gatech.edu>
Date: Wed, 3 Feb 2021 16:36:33 -0500
Subject: [PATCH 1/2] Fixes #80335
---
library/alloc/src/str.rs | 42 ++++++++++++++++++++++----------------
library/alloc/tests/str.rs | 30 +++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 70e0c7dba5eab..a7584c6b65100 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -90,8 +90,8 @@ impl<S: Borrow<str>> Join<&str> for [S] {
}
}
-macro_rules! spezialize_for_lengths {
- ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {
+macro_rules! specialize_for_lengths {
+ ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{
let mut target = $target;
let iter = $iter;
let sep_bytes = $separator;
@@ -102,7 +102,8 @@ macro_rules! spezialize_for_lengths {
$num => {
for s in iter {
copy_slice_and_advance!(target, sep_bytes);
- copy_slice_and_advance!(target, s.borrow().as_ref());
+ let content_bytes = s.borrow().as_ref();
+ copy_slice_and_advance!(target, content_bytes);
}
},
)*
@@ -110,11 +111,13 @@ macro_rules! spezialize_for_lengths {
// arbitrary non-zero size fallback
for s in iter {
copy_slice_and_advance!(target, sep_bytes);
- copy_slice_and_advance!(target, s.borrow().as_ref());
+ let content_bytes = s.borrow().as_ref();
+ copy_slice_and_advance!(target, content_bytes);
}
}
}
- };
+ target
+ }}
}
macro_rules! copy_slice_and_advance {
@@ -153,7 +156,7 @@ where
// if the `len` calculation overflows, we'll panic
// we would have run out of memory anyway and the rest of the function requires
// the entire Vec pre-allocated for safety
- let len = sep_len
+ let reserved_len = sep_len
.checked_mul(iter.len())
.and_then(|n| {
slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add)
@@ -161,22 +164,25 @@ where
.expect("attempt to join into collection with len > usize::MAX");
// crucial for safety
- let mut result = Vec::with_capacity(len);
- assert!(result.capacity() >= len);
+ let mut result = Vec::with_capacity(reserved_len);
+ debug_assert!(result.capacity() >= reserved_len);
result.extend_from_slice(first.borrow().as_ref());
unsafe {
- {
- let pos = result.len();
- let target = result.get_unchecked_mut(pos..len);
-
- // copy separator and slices over without bounds checks
- // generate loops with hardcoded offsets for small separators
- // massive improvements possible (~ x2)
- spezialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
- }
- result.set_len(len);
+ let pos = result.len();
+ let target = result.get_unchecked_mut(pos..reserved_len);
+
+ // copy separator and slices over without bounds checks
+ // generate loops with hardcoded offsets for small separators
+ // massive improvements possible (~ x2)
+ let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
+
+ // issue #80335: A weird borrow implementation can return different
+ // slices for the length calculation and the actual copy, so
+ // `remain.len()` might be non-zero.
+ let result_len = reserved_len - remain.len();
+ result.set_len(result_len);
}
result
}
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 604835e6cc4a6..6df8d8c2f354f 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -160,6 +160,36 @@ fn test_join_for_different_lengths_with_long_separator() {
test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
}
+#[test]
+fn test_join_isue_80335() {
+ use core::{borrow::Borrow, cell::Cell};
+
+ struct WeirdBorrow {
+ state: Cell<bool>,
+ }
+
+ impl Default for WeirdBorrow {
+ fn default() -> Self {
+ WeirdBorrow { state: Cell::new(false) }
+ }
+ }
+
+ impl Borrow<str> for WeirdBorrow {
+ fn borrow(&self) -> &str {
+ let state = self.state.get();
+ if state {
+ "0"
+ } else {
+ self.state.set(true);
+ "123456"
+ }
+ }
+ }
+
+ let arr: [WeirdBorrow; 3] = Default::default();
+ test_join!("0-0-0", arr, "-");
+}
+
#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_unsafe_slice() {
From 26a62701e42d10c03ce5f2f911e7d5edeefa2f0f Mon Sep 17 00:00:00 2001
From: Yechan Bae <yechan@gatech.edu>
Date: Sat, 20 Mar 2021 13:42:54 -0400
Subject: [PATCH 2/2] Update the comment
---
library/alloc/src/str.rs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index a7584c6b65100..4d1e876457b8e 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -163,7 +163,7 @@ where
})
.expect("attempt to join into collection with len > usize::MAX");
- // crucial for safety
+ // prepare an uninitialized buffer
let mut result = Vec::with_capacity(reserved_len);
debug_assert!(result.capacity() >= reserved_len);
@@ -178,9 +178,9 @@ where
// massive improvements possible (~ x2)
let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
- // issue #80335: A weird borrow implementation can return different
- // slices for the length calculation and the actual copy, so
- // `remain.len()` might be non-zero.
+ // A weird borrow implementation may return different
+ // slices for the length calculation and the actual copy.
+ // Make sure we don't expose uninitialized bytes to the caller.
let result_len = reserved_len - remain.len();
result.set_len(result_len);
}
From fa89c0fbcfa8f4d44f153b1195ec5a305540ffc4 Mon Sep 17 00:00:00 2001
From: The8472 <git@infinite-source.de>
Date: Mon, 29 Mar 2021 04:22:34 +0200
Subject: [PATCH 1/3] add testcase for double-drop during Vec in-place
collection
---
library/alloc/tests/vec.rs | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index c142536cd2dfb..b926c697d58ab 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1027,7 +1027,7 @@ fn test_from_iter_specialization_head_tail_drop() {
}
#[test]
-fn test_from_iter_specialization_panic_drop() {
+fn test_from_iter_specialization_panic_during_iteration_drops() {
let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect();
let src: Vec<_> = drop_count.iter().cloned().collect();
let iter = src.into_iter();
@@ -1050,6 +1050,42 @@ fn test_from_iter_specialization_panic_drop() {
);
}
+#[test]
+fn test_from_iter_specialization_panic_during_drop_leaks() {
+ static mut DROP_COUNTER: usize = 0;
+
+ #[derive(Debug)]
+ enum Droppable {
+ DroppedTwice(Box<i32>),
+ PanicOnDrop,
+ }
+
+ impl Drop for Droppable {
+ fn drop(&mut self) {
+ match self {
+ Droppable::DroppedTwice(_) => {
+ unsafe {
+ DROP_COUNTER += 1;
+ }
+ println!("Dropping!")
+ }
+ Droppable::PanicOnDrop => {
+ if !std::thread::panicking() {
+ panic!();
+ }
+ }
+ }
+ }
+ }
+
+ let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
+ let v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop];
+ let _ = v.into_iter().take(0).collect::<Vec<_>>();
+ }));
+
+ assert_eq!(unsafe { DROP_COUNTER }, 1);
+}
+
#[test]
fn test_cow_from() {
let borrowed: &[_] = &["borrowed", "(slice)"];
From 421f5d282a51e130d3ca7c4524d8ad6753437da9 Mon Sep 17 00:00:00 2001
From: The8472 <git@infinite-source.de>
Date: Mon, 29 Mar 2021 04:22:48 +0200
Subject: [PATCH 2/3] fix double-drop in in-place collect specialization
---
library/alloc/src/vec/into_iter.rs | 27 ++++++++++++++-------
library/alloc/src/vec/source_iter_marker.rs | 4 +--
2 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index bcbdffabc7fbe..324e894bafd23 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -85,20 +85,29 @@ impl<T, A: Allocator> IntoIter<T, A> {
ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
}
- pub(super) fn drop_remaining(&mut self) {
- unsafe {
- ptr::drop_in_place(self.as_mut_slice());
- }
- self.ptr = self.end;
- }
+ /// Drops remaining elements and relinquishes the backing allocation.
+ ///
+ /// This is roughly equivalent to the following, but more efficient
+ ///
+ /// ```
+ /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
+ /// (&mut into_iter).for_each(core::mem::drop);
+ /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
+ /// ```
+ pub(super) fn forget_allocation_drop_remaining(&mut self) {
+ let remaining = self.as_raw_mut_slice();
- /// Relinquishes the backing allocation, equivalent to
- /// `ptr::write(&mut self, Vec::new().into_iter())`
- pub(super) fn forget_allocation(&mut self) {
+ // overwrite the individual fields instead of creating a new
+ // struct and then overwriting &mut self.
+ // this creates less assembly
self.cap = 0;
self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
self.ptr = self.buf.as_ptr();
self.end = self.buf.as_ptr();
+
+ unsafe {
+ ptr::drop_in_place(remaining);
+ }
}
}
diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs
index 50882fc17673e..e857d284d3ab6 100644
--- a/library/alloc/src/vec/source_iter_marker.rs
+++ b/library/alloc/src/vec/source_iter_marker.rs
@@ -69,9 +69,9 @@ where
}
// drop any remaining values at the tail of the source
- src.drop_remaining();
// but prevent drop of the allocation itself once IntoIter goes out of scope
- src.forget_allocation();
+ // if the drop panics then we also leak any elements collected into dst_buf
+ src.forget_allocation_drop_remaining();
let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) };
From 328a5e040780984c60dde2db300dad4f1323c39d Mon Sep 17 00:00:00 2001
From: The8472 <git@infinite-source.de>
Date: Fri, 2 Apr 2021 23:06:05 +0200
Subject: [PATCH 3/3] cleanup leak after test to make miri happy
---
library/alloc/tests/vec.rs | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index b926c697d58ab..b9fe07c73e55e 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1,3 +1,4 @@
+use alloc::boxed::Box;
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::TryReserveError::*;
@@ -1056,14 +1057,14 @@ fn test_from_iter_specialization_panic_during_drop_leaks() {
#[derive(Debug)]
enum Droppable {
- DroppedTwice(Box<i32>),
+ DroppedTwice,
PanicOnDrop,
}
impl Drop for Droppable {
fn drop(&mut self) {
match self {
- Droppable::DroppedTwice(_) => {
+ Droppable::DroppedTwice => {
unsafe {
DROP_COUNTER += 1;
}
@@ -1078,12 +1079,21 @@ fn test_from_iter_specialization_panic_during_drop_leaks() {
}
}
+ let mut to_free: *mut Droppable = core::ptr::null_mut();
+ let mut cap = 0;
+
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
- let v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop];
+ let mut v = vec![Droppable::DroppedTwice, Droppable::PanicOnDrop];
+ to_free = v.as_mut_ptr();
+ cap = v.capacity();
let _ = v.into_iter().take(0).collect::<Vec<_>>();
}));
assert_eq!(unsafe { DROP_COUNTER }, 1);
+ // clean up the leak to keep miri happy
+ unsafe {
+ Vec::from_raw_parts(to_free, 0, cap);
+ }
}
#[test]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment