From 8dc75529ff7ed925204c94a59512c0e0e1056570 Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Wed, 16 Aug 2023 11:08:51 +0800 Subject: [PATCH] Fix CVE-2023-38497 Signed-off-by: Liwei Ge --- 0001-cargo-CVE-2023-38497.patch | 321 ++++++++ 0001-update-vendor-tar-to-0.4.39.patch | 971 +++++++++++++++++++++++++ rust.spec | 11 +- 3 files changed, 1302 insertions(+), 1 deletion(-) create mode 100644 0001-cargo-CVE-2023-38497.patch create mode 100644 0001-update-vendor-tar-to-0.4.39.patch diff --git a/0001-cargo-CVE-2023-38497.patch b/0001-cargo-CVE-2023-38497.patch new file mode 100644 index 0000000..c86f4f6 --- /dev/null +++ b/0001-cargo-CVE-2023-38497.patch @@ -0,0 +1,321 @@ +From 13030f7009233e040c2d9c52d8b61d8c53a71662 Mon Sep 17 00:00:00 2001 +From: Liwei Ge +Date: Wed, 16 Aug 2023 11:00:14 +0800 +Subject: [PATCH] fix CVE-2023-38497 + +backport from https://github.com/rust-lang/cargo/commit/ +d78bbf4bde3c6b95caca7512f537c6f9721426ff +--- + .../cargo/src/cargo/sources/registry/mod.rs | 55 +++++++- + src/tools/cargo/src/cargo/util/mod.rs | 18 +++ + src/tools/cargo/tests/testsuite/registry.rs | 130 +++++++++++++++++- + src/tools/cargo/tests/testsuite/vendor.rs | 5 +- + 4 files changed, 197 insertions(+), 11 deletions(-) + +diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs +index cabd4f9c6..6e0e97350 100644 +--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs ++++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs +@@ -161,17 +161,21 @@ + use std::borrow::Cow; + use std::collections::BTreeMap; + use std::collections::HashSet; ++use std::fs; + use std::fs::{File, OpenOptions}; ++use std::io; ++use std::io::Read; + use std::io::Write; + use std::path::{Path, PathBuf}; + use std::task::Poll; + + use anyhow::Context as _; +-use cargo_util::paths::exclude_from_backups_and_indexing; ++use cargo_util::paths::{self, exclude_from_backups_and_indexing}; + use flate2::read::GzDecoder; + use log::debug; + use semver::Version; + use serde::Deserialize; ++use serde::Serialize; + use tar::Archive; + + use crate::core::dependency::{DepKind, Dependency}; +@@ -198,6 +202,14 @@ const LOWER_PREFIX_TEMPLATE: &str = "{lowerprefix}"; + const CHECKSUM_TEMPLATE: &str = "{sha256-checksum}"; + const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024; + ++/// The content inside `.cargo-ok`. ++/// See [`RegistrySource::unpack_package`] for more. ++#[derive(Deserialize, Serialize)] ++struct LockMetadata { ++ /// The version of `.cargo-ok` file ++ v: u32, ++} ++ + /// A "source" for a local (see `local::LocalRegistry`) or remote (see + /// `remote::RemoteRegistry`) registry. + /// +@@ -608,18 +620,32 @@ impl<'cfg> RegistrySource<'cfg> { + // unpacked. + let package_dir = format!("{}-{}", pkg.name(), pkg.version()); + let dst = self.src_path.join(&package_dir); +- dst.create_dir()?; + let path = dst.join(PACKAGE_SOURCE_LOCK); + let path = self.config.assert_package_cache_locked(&path); + let unpack_dir = path.parent().unwrap(); +- if let Ok(meta) = path.metadata() { +- if meta.len() > 0 { +- return Ok(unpack_dir.to_path_buf()); +- } ++ match fs::read_to_string(path) { ++ Ok(ok) => match serde_json::from_str::(&ok) { ++ Ok(lock_meta) if lock_meta.v == 1 => { ++ return Ok(unpack_dir.to_path_buf()); ++ } ++ _ => { ++ if ok == "ok" { ++ log::debug!("old `ok` content found, clearing cache"); ++ } else { ++ log::warn!("unrecognized .cargo-ok content, clearing cache: {ok}"); ++ } ++ // See comment of `unpack_package` about why removing all stuff. ++ paths::remove_dir_all(dst.as_path_unlocked())?; ++ } ++ }, ++ Err(e) if e.kind() == io::ErrorKind::NotFound => {} ++ Err(e) => anyhow::bail!("unable to read .cargo-ok file at {path:?}: {e}"), + } ++ dst.create_dir()?; + let gz = GzDecoder::new(tarball); + let gz = LimitErrorReader::new(gz, max_unpack_size()); + let mut tar = Archive::new(gz); ++ set_mask(&mut tar); + let prefix = unpack_dir.file_name().unwrap(); + let parent = unpack_dir.parent().unwrap(); + for entry in tar.entries()? { +@@ -673,7 +699,9 @@ impl<'cfg> RegistrySource<'cfg> { + .write(true) + .open(&path) + .with_context(|| format!("failed to open `{}`", path.display()))?; +- write!(ok, "ok")?; ++ ++ let lock_meta = LockMetadata { v: 1 }; ++ write!(ok, "{}", serde_json::to_string(&lock_meta).unwrap())?; + + Ok(unpack_dir.to_path_buf()) + } +@@ -872,3 +900,16 @@ mod tests { + assert_eq!(make_dep_prefix("aBcDe"), "aB/cD"); + } + } ++ ++/// Set the current [`umask`] value for the given tarball. No-op on non-Unix ++/// platforms. ++/// ++/// On Windows, tar only looks at user permissions and tries to set the "read ++/// only" attribute, so no-op as well. ++/// ++/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html ++#[allow(unused_variables)] ++fn set_mask(tar: &mut Archive) { ++ #[cfg(unix)] ++ tar.set_mask(crate::util::get_umask()); ++} +diff --git a/src/tools/cargo/src/cargo/util/mod.rs b/src/tools/cargo/src/cargo/util/mod.rs +index 9881332ec..7fb491622 100644 +--- a/src/tools/cargo/src/cargo/util/mod.rs ++++ b/src/tools/cargo/src/cargo/util/mod.rs +@@ -122,3 +122,21 @@ pub fn truncate_with_ellipsis(s: &str, max_width: usize) -> String { + } + prefix + } ++/// Get the current [`umask`] value. ++/// ++/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html ++#[cfg(unix)] ++pub fn get_umask() -> u32 { ++ // SAFETY: Syscalls are unsafe. Calling `umask` twice is even unsafer for ++ // multithreading program, since it doesn't provide a way to retrive the ++ // value without modifications. We use a `lazy_static` here to ensure ++ // it only gets call once during the entire program lifetime. ++ lazy_static::lazy_static! { ++ static ref UMASK: libc::mode_t = unsafe { ++ let umask = libc::umask(0o022); ++ libc::umask(umask); ++ umask ++ }; ++ } ++ *UMASK as u32 // it is u16 on macos ++} +diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs +index 60c52fd54..ad95e1437 100644 +--- a/src/tools/cargo/tests/testsuite/registry.rs ++++ b/src/tools/cargo/tests/testsuite/registry.rs +@@ -2594,7 +2594,7 @@ fn package_lock_inside_package_is_overwritten() { + .join("bar-0.0.1") + .join(".cargo-ok"); + +- assert_eq!(ok.metadata().unwrap().len(), 2); ++ assert_eq!(ok.metadata().unwrap().len(), 7); + } + + #[cargo_test] +@@ -2634,7 +2634,7 @@ fn package_lock_as_a_symlink_inside_package_is_overwritten() { + let librs = pkg_root.join("src/lib.rs"); + + // Is correctly overwritten and doesn't affect the file linked to +- assert_eq!(ok.metadata().unwrap().len(), 2); ++ assert_eq!(ok.metadata().unwrap().len(), 7); + assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}"); + } + +@@ -2941,3 +2941,129 @@ required by package `foo v0.1.0 ([ROOT]/foo)` + .with_status(101) + .run(); + } ++ ++#[cfg(unix)] ++#[cargo_test] ++fn set_mask_during_unpacking() { ++ use std::os::unix::fs::MetadataExt; ++ ++ Package::new("bar", "1.0.0") ++ .file_with_mode("example.sh", 0o777, "#!/bin/sh") ++ .file_with_mode("src/lib.rs", 0o666, "") ++ .publish(); ++ ++ let p = project() ++ .file( ++ "Cargo.toml", ++ r#" ++ [package] ++ name = "foo" ++ version = "0.1.0" ++ ++ [dependencies] ++ bar = "1.0" ++ "#, ++ ) ++ .file("src/lib.rs", "") ++ .build(); ++ ++ p.cargo("fetch") ++ .with_stderr( ++ "\ ++[UPDATING] `dummy-registry` index ++[DOWNLOADING] crates ... ++[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) ++", ++ ) ++ .run(); ++ let src_file_path = |path: &str| { ++ glob::glob( ++ paths::home() ++ .join(".cargo/registry/src/*/bar-1.0.0/") ++ .join(path) ++ .to_str() ++ .unwrap(), ++ ) ++ .unwrap() ++ .next() ++ .unwrap() ++ .unwrap() ++ }; ++ ++ let umask = cargo::util::get_umask(); ++ let metadata = fs::metadata(src_file_path("src/lib.rs")).unwrap(); ++ assert_eq!(metadata.mode() & 0o777, 0o666 & !umask); ++ let metadata = fs::metadata(src_file_path("example.sh")).unwrap(); ++ assert_eq!(metadata.mode() & 0o777, 0o777 & !umask); ++} ++ ++#[cargo_test] ++fn unpack_again_when_cargo_ok_is_unrecognized() { ++ Package::new("bar", "1.0.0").publish(); ++ ++ let p = project() ++ .file( ++ "Cargo.toml", ++ r#" ++ [package] ++ name = "foo" ++ version = "0.1.0" ++ ++ [dependencies] ++ bar = "1.0" ++ "#, ++ ) ++ .file("src/lib.rs", "") ++ .build(); ++ ++ p.cargo("fetch") ++ .with_stderr( ++ "\ ++[UPDATING] `dummy-registry` index ++[DOWNLOADING] crates ... ++[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) ++", ++ ) ++ .run(); ++ ++ let src_file_path = |path: &str| { ++ glob::glob( ++ paths::home() ++ .join(".cargo/registry/src/*/bar-1.0.0/") ++ .join(path) ++ .to_str() ++ .unwrap(), ++ ) ++ .unwrap() ++ .next() ++ .unwrap() ++ .unwrap() ++ }; ++ ++ // Change permissions to simulate the old behavior not respecting umask. ++ let lib_rs = src_file_path("src/lib.rs"); ++ let cargo_ok = src_file_path(".cargo-ok"); ++ let mut perms = fs::metadata(&lib_rs).unwrap().permissions(); ++ assert!(!perms.readonly()); ++ perms.set_readonly(true); ++ fs::set_permissions(&lib_rs, perms).unwrap(); ++ let ok = fs::read_to_string(&cargo_ok).unwrap(); ++ assert_eq!(&ok, r#"{"v":1}"#); ++ ++ p.cargo("fetch").with_stderr("").run(); ++ ++ // Without changing `.cargo-ok`, a unpack won't be triggered. ++ let perms = fs::metadata(&lib_rs).unwrap().permissions(); ++ assert!(perms.readonly()); ++ ++ // Write "ok" to simulate the old behavior and trigger the unpack again. ++ fs::write(&cargo_ok, "ok").unwrap(); ++ ++ p.cargo("fetch").with_stderr("").run(); ++ ++ // Permission has been restored and `.cargo-ok` is in the new format. ++ let perms = fs::metadata(lib_rs).unwrap().permissions(); ++ assert!(!perms.readonly()); ++ let ok = fs::read_to_string(&cargo_ok).unwrap(); ++ assert_eq!(&ok, r#"{"v":1}"#); ++} +diff --git a/src/tools/cargo/tests/testsuite/vendor.rs b/src/tools/cargo/tests/testsuite/vendor.rs +index 8e985e265..db6f114ca 100644 +--- a/src/tools/cargo/tests/testsuite/vendor.rs ++++ b/src/tools/cargo/tests/testsuite/vendor.rs +@@ -890,10 +890,11 @@ fn vendor_preserves_permissions() { + + p.cargo("vendor --respect-source-config").run(); + ++ let umask = cargo::util::get_umask(); + let metadata = fs::metadata(p.root().join("vendor/bar/src/lib.rs")).unwrap(); +- assert_eq!(metadata.mode() & 0o777, 0o644); ++ assert_eq!(metadata.mode() & 0o777, 0o644 & !umask); + let metadata = fs::metadata(p.root().join("vendor/bar/example.sh")).unwrap(); +- assert_eq!(metadata.mode() & 0o777, 0o755); ++ assert_eq!(metadata.mode() & 0o777, 0o755 & !umask); + } + + #[cargo_test] +-- +2.27.0 + diff --git a/0001-update-vendor-tar-to-0.4.39.patch b/0001-update-vendor-tar-to-0.4.39.patch new file mode 100644 index 0000000..4bb2eb4 --- /dev/null +++ b/0001-update-vendor-tar-to-0.4.39.patch @@ -0,0 +1,971 @@ +From 705af5d2e609e685d4a5bc0ed68fc9d0cafafb8c Mon Sep 17 00:00:00 2001 +From: Liwei Ge +Date: Thu, 17 Aug 2023 15:25:40 +0800 +Subject: [PATCH] update vendor tar to 0.4.39 + +--- + Cargo.lock | 4 +- + src/bootstrap/Cargo.lock | 4 +- + src/tools/cargo/Cargo.toml | 4 +- + vendor/tar/.cargo-checksum.json | 2 +- + vendor/tar/Cargo.lock | 207 +++++++++++++++++++++----------- + vendor/tar/Cargo.toml | 18 ++- + vendor/tar/src/archive.rs | 29 +++++ + vendor/tar/src/entry.rs | 180 ++++++++++++++++++++++++--- + vendor/tar/tests/all.rs | 107 ++++++++++++++++- + vendor/tar/tests/entry.rs | 31 +++++ + 10 files changed, 485 insertions(+), 101 deletions(-) + +diff --git a/Cargo.lock b/Cargo.lock +index f89c3e3a8..216874ee8 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -4792,9 +4792,9 @@ dependencies = [ + + [[package]] + name = "tar" +-version = "0.4.38" ++version = "0.4.39" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" ++checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" + dependencies = [ + "filetime", + "libc", +diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock +index baecca44c..5b0147b1d 100644 +--- a/src/bootstrap/Cargo.lock ++++ b/src/bootstrap/Cargo.lock +@@ -622,9 +622,9 @@ dependencies = [ + + [[package]] + name = "tar" +-version = "0.4.38" ++version = "0.4.39" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" ++checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" + dependencies = [ + "filetime", + "libc", +diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml +index 4b4f328e1..78a8f5fdf 100644 +--- a/src/tools/cargo/Cargo.toml ++++ b/src/tools/cargo/Cargo.toml +@@ -58,7 +58,7 @@ serde-value = "0.7.0" + sha1 = "0.10.5" + shell-escape = "0.1.4" + strip-ansi-escapes = "0.1.0" +-tar = { version = "0.4.38", default-features = false } ++tar = { version = "0.4.39", default-features = false } + tempfile = "3.0" + termcolor = "1.1" + toml_edit = { version = "0.15.0", features = ["serde", "easy", "perf"] } +@@ -108,7 +108,7 @@ snapbox = { version = "0.3.0", features = ["diff", "path"] } + + [build-dependencies] + flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } +-tar = { version = "0.4.38", default-features = false } ++tar = { version = "0.4.39", default-features = false } + + [[bin]] + name = "cargo" +diff --git a/vendor/tar/.cargo-checksum.json b/vendor/tar/.cargo-checksum.json +index 508f784e8..792994f55 100644 +--- a/vendor/tar/.cargo-checksum.json ++++ b/vendor/tar/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"Cargo.lock":"9872bf9e41b9cadee45b688c9537030a993ca49a266fc7859029d8c74810d1d5","Cargo.toml":"8353c71aa4d394efa7aaeac3004d0a16fd0c7124b7bd57ea91ba87a7b2015f15","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"85a0091e02690c62379137988cd9b2689009536a0b941f1ab0581db26e9ebce6","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"705016636f7fdcad4fe20d7d2672be2b94cc53bb05e47628f5212b89e17a40fe","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"567a05d54e369d22efe40f3507a26e21f7878b95bd05c811250b2c350761791b","tests/entry.rs":"c1411ee09da9edb659b508867f0960e804966dfd33801f4a7afaefda331479dd","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"} +\ No newline at end of file ++{"files":{"Cargo.lock":"a074bb3491e0d988605218e794859ddb067bb624e793a053645fbbabadde83f6","Cargo.toml":"638559bf51f1b89359ece700138f774bc0a5c1513046e306d6109dc045799b84","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"71079f1a0962c2cf288058f38d24735bddabd1427ac2dee72ec18cc5ae4bceed","examples/extract_file.rs":"dc487f6631d824175afc3ee33de99e80718a8ca3f9e57fddd7cac0a46c07d3ae","examples/list.rs":"36e412205eaffea8ab7f39be4173594b74e36acb369e091362b1975ee4a7a14b","examples/raw_list.rs":"0a735576ac354457d6d5a4d395d044fae99bf67a7c69960ca784a6f6a1743651","examples/write.rs":"419ac3e4155035e32b52cd8e6ae987a2d99cf82f60abbfb315c2a2c4f8e8fd19","src/archive.rs":"9238c58f5a253034f490ede4c42de6e1b89986ee6db343920ee34b3dcfa5b238","src/builder.rs":"2914f394d44c133557532bf5765fe63e0def30ec0b447f8f2bc620e932a2036a","src/entry.rs":"0e4b0438cbc4cbec30a821ce8f23619fe9e53c17022a022de609d642e220193c","src/entry_type.rs":"0786688729a96b4a3135b28d40b95c3d4feaad66b9574c490cbea14814ab975f","src/error.rs":"a20813fbc52f1f2e3a79654f62de6001759f6504a06acee5b0819d4865398587","src/header.rs":"fb2b1fa943c19635826b3f2becfb82527be7d08fdac115af840da3ff06152908","src/lib.rs":"5468e413205c907c367c35d28a528389103d68fd6a5b5979bbedba7c9e6b6c99","src/pax.rs":"54002e31151f9c50e02a3da26b3cacd1d3c9a3902daee008ab76d112cf5a2430","tests/all.rs":"7a64869cd99a4642f2db71aa7d283633199e59b88ccca112cb467b0739e64e83","tests/entry.rs":"af12d84160e5459ebaee6ecdd68e0c811438c37c0cb881ad210e7f94132b9739","tests/header/mod.rs":"02b05639f63c39a47559650c7209817bb60282deb4f679d5b001ed936343d9de"},"package":"ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96"} +\ No newline at end of file +diff --git a/vendor/tar/Cargo.lock b/vendor/tar/Cargo.lock +index dd53b90b5..f63a631ad 100644 +--- a/vendor/tar/Cargo.lock ++++ b/vendor/tar/Cargo.lock +@@ -2,12 +2,24 @@ + # It is not intended for manual editing. + version = 3 + ++[[package]] ++name = "autocfg" ++version = "1.1.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" ++ + [[package]] + name = "bitflags" + version = "1.3.2" + source = "registry+https://github.com/rust-lang/crates.io-index" + checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + ++[[package]] ++name = "cc" ++version = "1.0.79" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" ++ + [[package]] + name = "cfg-if" + version = "1.0.0" +@@ -15,101 +27,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" + checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + + [[package]] +-name = "filetime" +-version = "0.2.15" ++name = "errno" ++version = "0.3.1" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" ++checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" + dependencies = [ +- "cfg-if", ++ "errno-dragonfly", + "libc", +- "redox_syscall", +- "winapi", ++ "windows-sys", + ] + + [[package]] +-name = "getrandom" +-version = "0.2.3" ++name = "errno-dragonfly" ++version = "0.1.2" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" ++checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" + dependencies = [ +- "cfg-if", ++ "cc", + "libc", +- "wasi", + ] + + [[package]] +-name = "libc" +-version = "0.2.103" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +- +-[[package]] +-name = "ppv-lite86" +-version = "0.2.10" ++name = "fastrand" ++version = "1.9.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" ++checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" ++dependencies = [ ++ "instant", ++] + + [[package]] +-name = "rand" +-version = "0.8.4" ++name = "filetime" ++version = "0.2.21" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" ++checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" + dependencies = [ ++ "cfg-if", + "libc", +- "rand_chacha", +- "rand_core", +- "rand_hc", ++ "redox_syscall 0.2.16", ++ "windows-sys", + ] + + [[package]] +-name = "rand_chacha" +-version = "0.3.1" ++name = "hermit-abi" ++version = "0.3.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" ++ ++[[package]] ++name = "instant" ++version = "0.1.12" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" ++checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" + dependencies = [ +- "ppv-lite86", +- "rand_core", ++ "cfg-if", + ] + + [[package]] +-name = "rand_core" +-version = "0.6.3" ++name = "io-lifetimes" ++version = "1.0.11" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" ++checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" + dependencies = [ +- "getrandom", ++ "hermit-abi", ++ "libc", ++ "windows-sys", + ] + + [[package]] +-name = "rand_hc" +-version = "0.3.1" ++name = "libc" ++version = "0.2.147" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++ ++[[package]] ++name = "linux-raw-sys" ++version = "0.3.8" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" ++checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" ++ ++[[package]] ++name = "redox_syscall" ++version = "0.2.16" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" + dependencies = [ +- "rand_core", ++ "bitflags", + ] + + [[package]] + name = "redox_syscall" +-version = "0.2.10" ++version = "0.3.5" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" ++checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" + dependencies = [ + "bitflags", + ] + + [[package]] +-name = "remove_dir_all" +-version = "0.5.3" ++name = "rustix" ++version = "0.37.23" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" ++checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" + dependencies = [ +- "winapi", ++ "bitflags", ++ "errno", ++ "io-lifetimes", ++ "libc", ++ "linux-raw-sys", ++ "windows-sys", + ] + + [[package]] + name = "tar" +-version = "0.4.38" ++version = "0.4.39" + dependencies = [ + "filetime", + "libc", +@@ -119,51 +150,89 @@ dependencies = [ + + [[package]] + name = "tempfile" +-version = "3.2.0" ++version = "3.6.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" ++checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" + dependencies = [ ++ "autocfg", + "cfg-if", +- "libc", +- "rand", +- "redox_syscall", +- "remove_dir_all", +- "winapi", ++ "fastrand", ++ "redox_syscall 0.3.5", ++ "rustix", ++ "windows-sys", + ] + + [[package]] +-name = "wasi" +-version = "0.10.2+wasi-snapshot-preview1" ++name = "windows-sys" ++version = "0.48.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" ++checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" ++dependencies = [ ++ "windows-targets", ++] + + [[package]] +-name = "winapi" +-version = "0.3.9" ++name = "windows-targets" ++version = "0.48.1" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" ++checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" + dependencies = [ +- "winapi-i686-pc-windows-gnu", +- "winapi-x86_64-pc-windows-gnu", ++ "windows_aarch64_gnullvm", ++ "windows_aarch64_msvc", ++ "windows_i686_gnu", ++ "windows_i686_msvc", ++ "windows_x86_64_gnu", ++ "windows_x86_64_gnullvm", ++ "windows_x86_64_msvc", + ] + + [[package]] +-name = "winapi-i686-pc-windows-gnu" +-version = "0.4.0" ++name = "windows_aarch64_gnullvm" ++version = "0.48.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" ++ ++[[package]] ++name = "windows_aarch64_msvc" ++version = "0.48.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" ++ ++[[package]] ++name = "windows_i686_gnu" ++version = "0.48.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" ++ ++[[package]] ++name = "windows_i686_msvc" ++version = "0.48.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" ++checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + + [[package]] +-name = "winapi-x86_64-pc-windows-gnu" +-version = "0.4.0" ++name = "windows_x86_64_gnu" ++version = "0.48.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" ++checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" ++ ++[[package]] ++name = "windows_x86_64_gnullvm" ++version = "0.48.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" ++ ++[[package]] ++name = "windows_x86_64_msvc" ++version = "0.48.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + + [[package]] + name = "xattr" +-version = "0.2.2" ++version = "0.2.3" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" ++checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" + dependencies = [ + "libc", + ] +diff --git a/vendor/tar/Cargo.toml b/vendor/tar/Cargo.toml +index 23771b564..6225b778f 100644 +--- a/vendor/tar/Cargo.toml ++++ b/vendor/tar/Cargo.toml +@@ -12,23 +12,35 @@ + [package] + edition = "2018" + name = "tar" +-version = "0.4.38" ++version = "0.4.39" + authors = ["Alex Crichton "] + exclude = ["tests/archives/*"] +-description = "A Rust implementation of a TAR file reader and writer. This library does not\ncurrently handle compression, but it is abstract over all I/O readers and\nwriters. Additionally, great lengths are taken to ensure that the entire\ncontents are never required to be entirely resident in memory all at once.\n" ++description = """ ++A Rust implementation of a TAR file reader and writer. This library does not ++currently handle compression, but it is abstract over all I/O readers and ++writers. Additionally, great lengths are taken to ensure that the entire ++contents are never required to be entirely resident in memory all at once. ++""" + homepage = "https://github.com/alexcrichton/tar-rs" + documentation = "https://docs.rs/tar" + readme = "README.md" +-keywords = ["tar", "tarfile", "encoding"] ++keywords = [ ++ "tar", ++ "tarfile", ++ "encoding", ++] + license = "MIT/Apache-2.0" + repository = "https://github.com/alexcrichton/tar-rs" ++ + [dependencies.filetime] + version = "0.2.8" ++ + [dev-dependencies.tempfile] + version = "3" + + [features] + default = ["xattr"] ++ + [target."cfg(unix)".dependencies.libc] + version = "0.2" + +diff --git a/vendor/tar/src/archive.rs b/vendor/tar/src/archive.rs +index 1bed51249..c7a9d9803 100644 +--- a/vendor/tar/src/archive.rs ++++ b/vendor/tar/src/archive.rs +@@ -22,8 +22,10 @@ pub struct Archive { + + pub struct ArchiveInner { + pos: Cell, ++ mask: u32, + unpack_xattrs: bool, + preserve_permissions: bool, ++ preserve_ownerships: bool, + preserve_mtime: bool, + overwrite: bool, + ignore_zeros: bool, +@@ -52,8 +54,10 @@ impl Archive { + pub fn new(obj: R) -> Archive { + Archive { + inner: ArchiveInner { ++ mask: u32::MIN, + unpack_xattrs: false, + preserve_permissions: false, ++ preserve_ownerships: false, + preserve_mtime: true, + overwrite: true, + ignore_zeros: false, +@@ -106,6 +110,20 @@ impl Archive { + me._unpack(dst.as_ref()) + } + ++ /// Set the mask of the permission bits when unpacking this entry. ++ /// ++ /// The mask will be inverted when applying against a mode, similar to how ++ /// `umask` works on Unix. In logical notation it looks like: ++ /// ++ /// ```text ++ /// new_mode = old_mode & (~mask) ++ /// ``` ++ /// ++ /// The mask is 0 by default and is currently only implemented on Unix. ++ pub fn set_mask(&mut self, mask: u32) { ++ self.inner.mask = mask; ++ } ++ + /// Indicate whether extended file attributes (xattrs on Unix) are preserved + /// when unpacking this archive. + /// +@@ -126,6 +144,15 @@ impl Archive { + self.inner.preserve_permissions = preserve; + } + ++ /// Indicate whether numeric ownership ids (like uid and gid on Unix) ++ /// are preserved when unpacking this entry. ++ /// ++ /// This flag is disabled by default and is currently only implemented on ++ /// Unix. ++ pub fn set_preserve_ownerships(&mut self, preserve: bool) { ++ self.inner.preserve_ownerships = preserve; ++ } ++ + /// Indicate whether files and symlinks should be overwritten on extraction. + pub fn set_overwrite(&mut self, overwrite: bool) { + self.inner.overwrite = overwrite; +@@ -304,10 +331,12 @@ impl<'a> EntriesFields<'a> { + long_pathname: None, + long_linkname: None, + pax_extensions: None, ++ mask: self.archive.inner.mask, + unpack_xattrs: self.archive.inner.unpack_xattrs, + preserve_permissions: self.archive.inner.preserve_permissions, + preserve_mtime: self.archive.inner.preserve_mtime, + overwrite: self.archive.inner.overwrite, ++ preserve_ownerships: self.archive.inner.preserve_ownerships, + }; + + // Store where the next entry is, rounding up by 512 bytes (the size of +diff --git a/vendor/tar/src/entry.rs b/vendor/tar/src/entry.rs +index 8f0b62acf..c81554fcb 100644 +--- a/vendor/tar/src/entry.rs ++++ b/vendor/tar/src/entry.rs +@@ -31,6 +31,7 @@ pub struct EntryFields<'a> { + pub long_pathname: Option>, + pub long_linkname: Option>, + pub pax_extensions: Option>, ++ pub mask: u32, + pub header: Header, + pub size: u64, + pub header_pos: u64, +@@ -38,6 +39,7 @@ pub struct EntryFields<'a> { + pub data: Vec>, + pub unpack_xattrs: bool, + pub preserve_permissions: bool, ++ pub preserve_ownerships: bool, + pub preserve_mtime: bool, + pub overwrite: bool, + } +@@ -230,6 +232,20 @@ impl<'a, R: Read> Entry<'a, R> { + self.fields.unpack_in(dst.as_ref()) + } + ++ /// Set the mask of the permission bits when unpacking this entry. ++ /// ++ /// The mask will be inverted when applying against a mode, similar to how ++ /// `umask` works on Unix. In logical notation it looks like: ++ /// ++ /// ```text ++ /// new_mode = old_mode & (~mask) ++ /// ``` ++ /// ++ /// The mask is 0 by default and is currently only implemented on Unix. ++ pub fn set_mask(&mut self, mask: u32) { ++ self.fields.mask = mask; ++ } ++ + /// Indicate whether extended file attributes (xattrs on Unix) are preserved + /// when unpacking this entry. + /// +@@ -444,13 +460,51 @@ impl<'a> EntryFields<'a> { + + /// Returns access to the header of this entry in the archive. + fn unpack(&mut self, target_base: Option<&Path>, dst: &Path) -> io::Result { ++ fn set_perms_ownerships( ++ dst: &Path, ++ f: Option<&mut std::fs::File>, ++ header: &Header, ++ mask: u32, ++ perms: bool, ++ ownerships: bool, ++ ) -> io::Result<()> { ++ // ownerships need to be set first to avoid stripping SUID bits in the permissions ... ++ if ownerships { ++ set_ownerships(dst, &f, header.uid()?, header.gid()?)?; ++ } ++ // ... then set permissions, SUID bits set here is kept ++ if let Ok(mode) = header.mode() { ++ set_perms(dst, f, mode, mask, perms)?; ++ } ++ ++ Ok(()) ++ } ++ ++ fn get_mtime(header: &Header) -> Option { ++ header.mtime().ok().map(|mtime| { ++ // For some more information on this see the comments in ++ // `Header::fill_platform_from`, but the general idea is that ++ // we're trying to avoid 0-mtime files coming out of archives ++ // since some tools don't ingest them well. Perhaps one day ++ // when Cargo stops working with 0-mtime archives we can remove ++ // this. ++ let mtime = if mtime == 0 { 1 } else { mtime }; ++ FileTime::from_unix_time(mtime as i64, 0) ++ }) ++ } ++ + let kind = self.header.entry_type(); + + if kind.is_dir() { + self.unpack_dir(dst)?; +- if let Ok(mode) = self.header.mode() { +- set_perms(dst, None, mode, self.preserve_permissions)?; +- } ++ set_perms_ownerships( ++ dst, ++ None, ++ &self.header, ++ self.mask, ++ self.preserve_permissions, ++ self.preserve_ownerships, ++ )?; + return Ok(Unpacked::__Nonexhaustive); + } else if kind.is_hard_link() || kind.is_symlink() { + let src = match self.link_name()? { +@@ -522,7 +576,14 @@ impl<'a> EntryFields<'a> { + ), + ) + })?; +- }; ++ if self.preserve_mtime { ++ if let Some(mtime) = get_mtime(&self.header) { ++ filetime::set_symlink_file_times(dst, mtime, mtime).map_err(|e| { ++ TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) ++ })?; ++ } ++ } ++ } + return Ok(Unpacked::__Nonexhaustive); + + #[cfg(target_arch = "wasm32")] +@@ -553,9 +614,14 @@ impl<'a> EntryFields<'a> { + // Only applies to old headers. + if self.header.as_ustar().is_none() && self.path_bytes().ends_with(b"/") { + self.unpack_dir(dst)?; +- if let Ok(mode) = self.header.mode() { +- set_perms(dst, None, mode, self.preserve_permissions)?; +- } ++ set_perms_ownerships( ++ dst, ++ None, ++ &self.header, ++ self.mask, ++ self.preserve_permissions, ++ self.preserve_ownerships, ++ )?; + return Ok(Unpacked::__Nonexhaustive); + } + +@@ -618,35 +684,105 @@ impl<'a> EntryFields<'a> { + })?; + + if self.preserve_mtime { +- if let Ok(mtime) = self.header.mtime() { +- // For some more information on this see the comments in +- // `Header::fill_platform_from`, but the general idea is that +- // we're trying to avoid 0-mtime files coming out of archives +- // since some tools don't ingest them well. Perhaps one day +- // when Cargo stops working with 0-mtime archives we can remove +- // this. +- let mtime = if mtime == 0 { 1 } else { mtime }; +- let mtime = FileTime::from_unix_time(mtime as i64, 0); ++ if let Some(mtime) = get_mtime(&self.header) { + filetime::set_file_handle_times(&f, Some(mtime), Some(mtime)).map_err(|e| { + TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) + })?; + } + } +- if let Ok(mode) = self.header.mode() { +- set_perms(dst, Some(&mut f), mode, self.preserve_permissions)?; +- } ++ set_perms_ownerships( ++ dst, ++ Some(&mut f), ++ &self.header, ++ self.mask, ++ self.preserve_permissions, ++ self.preserve_ownerships, ++ )?; + if self.unpack_xattrs { + set_xattrs(self, dst)?; + } + return Ok(Unpacked::File(f)); + ++ fn set_ownerships( ++ dst: &Path, ++ f: &Option<&mut std::fs::File>, ++ uid: u64, ++ gid: u64, ++ ) -> Result<(), TarError> { ++ _set_ownerships(dst, f, uid, gid).map_err(|e| { ++ TarError::new( ++ format!( ++ "failed to set ownerships to uid={:?}, gid={:?} \ ++ for `{}`", ++ uid, ++ gid, ++ dst.display() ++ ), ++ e, ++ ) ++ }) ++ } ++ ++ #[cfg(unix)] ++ fn _set_ownerships( ++ dst: &Path, ++ f: &Option<&mut std::fs::File>, ++ uid: u64, ++ gid: u64, ++ ) -> io::Result<()> { ++ use std::convert::TryInto; ++ use std::os::unix::prelude::*; ++ ++ let uid: libc::uid_t = uid.try_into().map_err(|_| { ++ io::Error::new(io::ErrorKind::Other, format!("UID {} is too large!", uid)) ++ })?; ++ let gid: libc::gid_t = gid.try_into().map_err(|_| { ++ io::Error::new(io::ErrorKind::Other, format!("GID {} is too large!", gid)) ++ })?; ++ match f { ++ Some(f) => unsafe { ++ let fd = f.as_raw_fd(); ++ if libc::fchown(fd, uid, gid) != 0 { ++ Err(io::Error::last_os_error()) ++ } else { ++ Ok(()) ++ } ++ }, ++ None => unsafe { ++ let path = std::ffi::CString::new(dst.as_os_str().as_bytes()).map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("path contains null character: {:?}", e), ++ ) ++ })?; ++ if libc::lchown(path.as_ptr(), uid, gid) != 0 { ++ Err(io::Error::last_os_error()) ++ } else { ++ Ok(()) ++ } ++ }, ++ } ++ } ++ ++ // Windows does not support posix numeric ownership IDs ++ #[cfg(any(windows, target_arch = "wasm32"))] ++ fn _set_ownerships( ++ _: &Path, ++ _: &Option<&mut std::fs::File>, ++ _: u64, ++ _: u64, ++ ) -> io::Result<()> { ++ Ok(()) ++ } ++ + fn set_perms( + dst: &Path, + f: Option<&mut std::fs::File>, + mode: u32, ++ mask: u32, + preserve: bool, + ) -> Result<(), TarError> { +- _set_perms(dst, f, mode, preserve).map_err(|e| { ++ _set_perms(dst, f, mode, mask, preserve).map_err(|e| { + TarError::new( + format!( + "failed to set permissions to {:o} \ +@@ -664,11 +800,13 @@ impl<'a> EntryFields<'a> { + dst: &Path, + f: Option<&mut std::fs::File>, + mode: u32, ++ mask: u32, + preserve: bool, + ) -> io::Result<()> { + use std::os::unix::prelude::*; + + let mode = if preserve { mode } else { mode & 0o777 }; ++ let mode = mode & !mask; + let perm = fs::Permissions::from_mode(mode as _); + match f { + Some(f) => f.set_permissions(perm), +@@ -681,6 +819,7 @@ impl<'a> EntryFields<'a> { + dst: &Path, + f: Option<&mut std::fs::File>, + mode: u32, ++ _mask: u32, + _preserve: bool, + ) -> io::Result<()> { + if mode & 0o200 == 0o200 { +@@ -706,6 +845,7 @@ impl<'a> EntryFields<'a> { + dst: &Path, + f: Option<&mut std::fs::File>, + mode: u32, ++ mask: u32, + _preserve: bool, + ) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) +diff --git a/vendor/tar/tests/all.rs b/vendor/tar/tests/all.rs +index 11103bd6b..8c5359c56 100644 +--- a/vendor/tar/tests/all.rs ++++ b/vendor/tar/tests/all.rs +@@ -579,10 +579,21 @@ fn extracting_malicious_tarball() { + t!(a.append(&header, io::repeat(1).take(1))); + }; + append("/tmp/abs_evil.txt"); +- append("//tmp/abs_evil2.txt"); ++ // std parse `//` as UNC path, see rust-lang/rust#100833 ++ append( ++ #[cfg(not(windows))] ++ "//tmp/abs_evil2.txt", ++ #[cfg(windows)] ++ "C://tmp/abs_evil2.txt", ++ ); + append("///tmp/abs_evil3.txt"); + append("/./tmp/abs_evil4.txt"); +- append("//./tmp/abs_evil5.txt"); ++ append( ++ #[cfg(not(windows))] ++ "//./tmp/abs_evil5.txt", ++ #[cfg(windows)] ++ "C://./tmp/abs_evil5.txt", ++ ); + append("///./tmp/abs_evil6.txt"); + append("/../tmp/rel_evil.txt"); + append("../rel_evil2.txt"); +@@ -757,6 +768,40 @@ fn backslash_treated_well() { + assert!(fs::metadata(td.path().join("foo\\bar")).is_ok()); + } + ++#[test] ++#[cfg(unix)] ++fn set_mask() { ++ use ::std::os::unix::fs::PermissionsExt; ++ let mut ar = tar::Builder::new(Vec::new()); ++ ++ let mut header = tar::Header::new_gnu(); ++ header.set_size(0); ++ header.set_entry_type(tar::EntryType::Regular); ++ t!(header.set_path("foo")); ++ header.set_mode(0o777); ++ header.set_cksum(); ++ t!(ar.append(&header, &[][..])); ++ ++ let mut header = tar::Header::new_gnu(); ++ header.set_size(0); ++ header.set_entry_type(tar::EntryType::Regular); ++ t!(header.set_path("bar")); ++ header.set_mode(0o421); ++ header.set_cksum(); ++ t!(ar.append(&header, &[][..])); ++ ++ let td = t!(TempBuilder::new().prefix("tar-rs").tempdir()); ++ let bytes = t!(ar.into_inner()); ++ let mut ar = tar::Archive::new(&bytes[..]); ++ ar.set_mask(0o211); ++ t!(ar.unpack(td.path())); ++ ++ let md = t!(fs::metadata(td.path().join("foo"))); ++ assert_eq!(md.permissions().mode(), 0o100566); ++ let md = t!(fs::metadata(td.path().join("bar"))); ++ assert_eq!(md.permissions().mode(), 0o100420); ++} ++ + #[cfg(unix)] + #[test] + fn nul_bytes_in_path() { +@@ -792,6 +837,10 @@ fn unpack_links() { + + let md = t!(fs::symlink_metadata(td.path().join("lnk"))); + assert!(md.file_type().is_symlink()); ++ ++ let mtime = FileTime::from_last_modification_time(&md); ++ assert_eq!(mtime.unix_seconds(), 1448291033); ++ + assert_eq!( + &*t!(fs::read_link(td.path().join("lnk"))), + Path::new("file") +@@ -1385,3 +1434,57 @@ fn header_size_overflow() { + err + ); + } ++ ++#[test] ++#[cfg(unix)] ++fn ownership_preserving() { ++ use std::os::unix::prelude::*; ++ ++ let mut rdr = Vec::new(); ++ let mut ar = Builder::new(&mut rdr); ++ let data: &[u8] = &[]; ++ let mut header = Header::new_gnu(); ++ // file 1 with uid = 580800000, gid = 580800000 ++ header.set_gid(580800000); ++ header.set_uid(580800000); ++ t!(header.set_path("iamuid580800000")); ++ header.set_size(0); ++ header.set_cksum(); ++ t!(ar.append(&header, data)); ++ // file 2 with uid = 580800001, gid = 580800000 ++ header.set_uid(580800001); ++ t!(header.set_path("iamuid580800001")); ++ header.set_cksum(); ++ t!(ar.append(&header, data)); ++ // file 3 with uid = 580800002, gid = 580800002 ++ header.set_gid(580800002); ++ header.set_uid(580800002); ++ t!(header.set_path("iamuid580800002")); ++ header.set_cksum(); ++ t!(ar.append(&header, data)); ++ t!(ar.finish()); ++ ++ let rdr = Cursor::new(t!(ar.into_inner())); ++ let td = t!(TempBuilder::new().prefix("tar-rs").tempdir()); ++ let mut ar = Archive::new(rdr); ++ ar.set_preserve_ownerships(true); ++ ++ if unsafe { libc::getuid() } == 0 { ++ assert!(ar.unpack(td.path()).is_ok()); ++ // validate against premade files ++ // iamuid580800001 has this ownership: 580800001:580800000 ++ let meta = std::fs::metadata(td.path().join("iamuid580800000")).unwrap(); ++ assert_eq!(meta.uid(), 580800000); ++ assert_eq!(meta.gid(), 580800000); ++ let meta = std::fs::metadata(td.path().join("iamuid580800001")).unwrap(); ++ assert_eq!(meta.uid(), 580800001); ++ assert_eq!(meta.gid(), 580800000); ++ let meta = std::fs::metadata(td.path().join("iamuid580800002")).unwrap(); ++ assert_eq!(meta.uid(), 580800002); ++ assert_eq!(meta.gid(), 580800002); ++ } else { ++ // it's not possible to unpack tar while preserving ownership ++ // without root permissions ++ assert!(ar.unpack(td.path()).is_err()); ++ } ++} +diff --git a/vendor/tar/tests/entry.rs b/vendor/tar/tests/entry.rs +index fa8eeaee7..62df663e8 100644 +--- a/vendor/tar/tests/entry.rs ++++ b/vendor/tar/tests/entry.rs +@@ -180,6 +180,37 @@ fn directory_maintains_permissions() { + assert_eq!(md.permissions().mode(), 0o40777); + } + ++#[test] ++#[cfg(unix)] ++fn set_entry_mask() { ++ use ::std::os::unix::fs::PermissionsExt; ++ ++ let mut ar = tar::Builder::new(Vec::new()); ++ ++ let mut header = tar::Header::new_gnu(); ++ header.set_size(0); ++ header.set_entry_type(tar::EntryType::Regular); ++ t!(header.set_path("foo")); ++ header.set_mode(0o777); ++ header.set_cksum(); ++ t!(ar.append(&header, &[][..])); ++ ++ let bytes = t!(ar.into_inner()); ++ let mut ar = tar::Archive::new(&bytes[..]); ++ let td = t!(Builder::new().prefix("tar").tempdir()); ++ let foo_path = td.path().join("foo"); ++ ++ let mut entries = t!(ar.entries()); ++ let mut foo = t!(entries.next().unwrap()); ++ foo.set_mask(0o027); ++ t!(foo.unpack(&foo_path)); ++ ++ let f = t!(File::open(foo_path)); ++ let md = t!(f.metadata()); ++ assert!(md.is_file()); ++ assert_eq!(md.permissions().mode(), 0o100750); ++} ++ + #[test] + #[cfg(not(windows))] // dangling symlinks have weird permissions + fn modify_link_just_created() { +-- +2.27.0 + diff --git a/rust.spec b/rust.spec index 2063175..e652f7f 100644 --- a/rust.spec +++ b/rust.spec @@ -88,7 +88,7 @@ Name: rust Version: 1.66.1 -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) @@ -135,6 +135,9 @@ Patch101: rustc-1.65.0-disable-http2.patch # (affects RHEL6 kernels when building for RHEL7) Patch102: rustc-1.65.0-no-default-pie.patch +Patch1000: 0001-cargo-CVE-2023-38497.patch +Patch1001: 0001-update-vendor-tar-to-0.4.39.patch + # Get the Rust triple for any arch. %{lua: function rust_triple(arch) @@ -611,6 +614,9 @@ rm -rf vendor/libnghttp2-sys/ %patch102 -p1 %endif +%patch1000 -p1 +%patch1001 -p1 + # Use our explicit python3 first sed -i.try-python -e '/^try python3 /i try "%{__python3}" "$@"' ./configure @@ -1061,6 +1067,9 @@ end} %changelog +* Wed Aug 16 2023 Liwei Ge - 1.66.1-2 +- Fix CVE-2023-38497 + * Wed Jan 11 2023 Josh Stone - 1.66.1-1 - Update to 1.66.1. -- Gitee