103 lines
3.8 KiB
Diff
103 lines
3.8 KiB
Diff
|
From d1f9553c825f6d7481453be8d58d0e7f117988a7 Mon Sep 17 00:00:00 2001
|
||
|
From: Josh Triplett <josh@joshtriplett.org>
|
||
|
Date: Thu, 18 Aug 2022 17:45:45 +0200
|
||
|
Subject: [PATCH] CVE-2022-36114: limit the maximum unpacked size of a crate to
|
||
|
512MB
|
||
|
|
||
|
This gives users of custom registries the same protections, using the
|
||
|
same size limit that crates.io uses.
|
||
|
|
||
|
`LimitErrorReader` code copied from crates.io.
|
||
|
---
|
||
|
src/cargo/sources/registry/mod.rs | 6 +++++-
|
||
|
src/cargo/util/io.rs | 27 +++++++++++++++++++++++++++
|
||
|
src/cargo/util/mod.rs | 2 ++
|
||
|
3 files changed, 34 insertions(+), 1 deletion(-)
|
||
|
create mode 100644 src/cargo/util/io.rs
|
||
|
gyakovlev: 'sed -i 's|/src/cargo|/src/tools/cargo/src/cargo|g'
|
||
|
|
||
|
diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs
|
||
|
index a2863bf78a..c9c414e500 100644
|
||
|
--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs
|
||
|
+++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs
|
||
|
@@ -182,7 +182,9 @@ use crate::util::hex;
|
||
|
use crate::util::interning::InternedString;
|
||
|
use crate::util::into_url::IntoUrl;
|
||
|
use crate::util::network::PollExt;
|
||
|
-use crate::util::{restricted_names, CargoResult, Config, Filesystem, OptVersionReq};
|
||
|
+use crate::util::{
|
||
|
+ restricted_names, CargoResult, Config, Filesystem, LimitErrorReader, OptVersionReq,
|
||
|
+};
|
||
|
|
||
|
const PACKAGE_SOURCE_LOCK: &str = ".cargo-ok";
|
||
|
pub const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index";
|
||
|
@@ -194,6 +196,7 @@ const VERSION_TEMPLATE: &str = "{version}";
|
||
|
const PREFIX_TEMPLATE: &str = "{prefix}";
|
||
|
const LOWER_PREFIX_TEMPLATE: &str = "{lowerprefix}";
|
||
|
const CHECKSUM_TEMPLATE: &str = "{sha256-checksum}";
|
||
|
+const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024;
|
||
|
|
||
|
/// A "source" for a local (see `local::LocalRegistry`) or remote (see
|
||
|
/// `remote::RemoteRegistry`) registry.
|
||
|
@@ -615,6 +618,7 @@ impl<'cfg> RegistrySource<'cfg> {
|
||
|
}
|
||
|
}
|
||
|
let gz = GzDecoder::new(tarball);
|
||
|
+ let gz = LimitErrorReader::new(gz, MAX_UNPACK_SIZE);
|
||
|
let mut tar = Archive::new(gz);
|
||
|
let prefix = unpack_dir.file_name().unwrap();
|
||
|
let parent = unpack_dir.parent().unwrap();
|
||
|
diff --git a/src/tools/cargo/src/cargo/util/io.rs b/src/tools/cargo/src/cargo/util/io.rs
|
||
|
new file mode 100644
|
||
|
index 0000000000..f62672db03
|
||
|
--- /dev/null
|
||
|
+++ b/src/tools/cargo/src/cargo/util/io.rs
|
||
|
@@ -0,0 +1,27 @@
|
||
|
+use std::io::{self, Read, Take};
|
||
|
+
|
||
|
+#[derive(Debug)]
|
||
|
+pub struct LimitErrorReader<R> {
|
||
|
+ inner: Take<R>,
|
||
|
+}
|
||
|
+
|
||
|
+impl<R: Read> LimitErrorReader<R> {
|
||
|
+ pub fn new(r: R, limit: u64) -> LimitErrorReader<R> {
|
||
|
+ LimitErrorReader {
|
||
|
+ inner: r.take(limit),
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+impl<R: Read> Read for LimitErrorReader<R> {
|
||
|
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||
|
+ match self.inner.read(buf) {
|
||
|
+ Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(
|
||
|
+ io::ErrorKind::Other,
|
||
|
+ "maximum limit reached when reading",
|
||
|
+ )),
|
||
|
+ e => e,
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
diff --git a/src/tools/cargo/src/cargo/util/mod.rs b/src/tools/cargo/src/cargo/util/mod.rs
|
||
|
index 28f685c209..47bbf37aad 100644
|
||
|
--- a/src/tools/cargo/src/cargo/util/mod.rs
|
||
|
+++ b/src/tools/cargo/src/cargo/util/mod.rs
|
||
|
@@ -14,6 +14,7 @@ pub use self::hasher::StableHasher;
|
||
|
pub use self::hex::{hash_u64, short_hash, to_hex};
|
||
|
pub use self::into_url::IntoUrl;
|
||
|
pub use self::into_url_with_base::IntoUrlWithBase;
|
||
|
+pub(crate) use self::io::LimitErrorReader;
|
||
|
pub use self::lev_distance::{closest, closest_msg, lev_distance};
|
||
|
pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};
|
||
|
pub use self::progress::{Progress, ProgressStyle};
|
||
|
@@ -44,6 +45,7 @@ pub mod important_paths;
|
||
|
pub mod interning;
|
||
|
pub mod into_url;
|
||
|
mod into_url_with_base;
|
||
|
+mod io;
|
||
|
pub mod job;
|
||
|
pub mod lev_distance;
|
||
|
mod lockserver;
|