diff --git a/Cargo.lock b/Cargo.lock
index 721959945a..ec428c8a4a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6242,9 +6242,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tar"
-version = "0.4.35"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80"
+checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
dependencies = [
"filetime",
"libc",
diff --git a/download-utils/Cargo.toml b/download-utils/Cargo.toml
index 0f9d84b14e..995457566b 100644
--- a/download-utils/Cargo.toml
+++ b/download-utils/Cargo.toml
@@ -17,7 +17,7 @@ log = "0.4.14"
reqwest = { version = "0.11.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
solana-sdk = { path = "../sdk", version = "=1.8.0" }
solana-runtime = { path = "../runtime", version = "=1.8.0" }
-tar = "0.4.35"
+tar = "0.4.37"
[lib]
crate-type = ["lib"]
diff --git a/install/Cargo.toml b/install/Cargo.toml
index 5198b8ea7e..234a38e964 100644
--- a/install/Cargo.toml
+++ b/install/Cargo.toml
@@ -32,7 +32,7 @@ solana-logger = { path = "../logger", version = "=1.8.0" }
solana-sdk = { path = "../sdk", version = "=1.8.0" }
solana-version = { path = "../version", version = "=1.8.0" }
semver = "1.0.4"
-tar = "0.4.35"
+tar = "0.4.37"
tempfile = "3.2.0"
url = "2.2.2"
diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock
index f1909b5c76..134203ce34 100644
--- a/programs/bpf/Cargo.lock
+++ b/programs/bpf/Cargo.lock
@@ -3487,9 +3487,9 @@ dependencies = [
[[package]]
name = "tar"
-version = "0.4.35"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80"
+checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
dependencies = [
"filetime",
"libc",
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index b475d53c9f..c920bf0a61 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -49,7 +49,7 @@ solana-secp256k1-program = { path = "../programs/secp256k1", version = "=1.8.0"
solana-stake-program = { path = "../programs/stake", version = "=1.8.0" }
solana-vote-program = { path = "../programs/vote", version = "=1.8.0" }
symlink = "0.1.0"
-tar = "0.4.35"
+tar = "0.4.37"
tempfile = "3.2.0"
thiserror = "1.0"
zstd = "0.9.0"
diff --git a/runtime/src/hardened_unpack.rs b/runtime/src/hardened_unpack.rs
index fdaa424f6c..7580ab4b10 100644
--- a/runtime/src/hardened_unpack.rs
+++ b/runtime/src/hardened_unpack.rs
@@ -9,7 +9,7 @@ use {
fs::{self, File},
io::{BufReader, Read},
path::{
- Component::{CurDir, Normal},
+ Component::{self, CurDir, Normal},
Path, PathBuf,
},
time::Instant,
@@ -161,9 +161,14 @@ where
)?;
total_count = checked_total_count_increment(total_count, limit_count)?;
- // unpack_in does its own sanitization
- // ref: https://docs.rs/tar/*/tar/struct.Entry.html#method.unpack_in
- check_unpack_result(entry.unpack_in(unpack_dir)?, path_str)?;
+ let target = sanitize_path(&entry.path()?, unpack_dir)?; // ? handles file system errors
+ if target.is_none() {
+ continue; // skip it
+ }
+ let target = target.unwrap();
+
+ let unpack = entry.unpack(target);
+ check_unpack_result(unpack.map(|_unpack| true)?, path_str)?;
// Sanitize permissions.
let mode = match entry.header().entry_type() {
@@ -199,6 +204,80 @@ where
}
}
+// return Err on file system error
+// return Some(path) if path is good
+// return None if we should skip this file
+fn sanitize_path(entry_path: &Path, dst: &Path) -> Result