fix(rust-volume-server): build backend binary into a private cache dir

A preexisting executable in a world-writable temp path could have been
planted by another local user; only reuse the cache when the directory
is verifiably ours, and otherwise build in a per-process directory.
This commit is contained in:
user.email committed 2026-10-24 22:45:25 -07:00
1 parent 76597324e6
commit b571ced535
1 file changed
+35 -3
+35 -3
View File
@@ -1117,9 +1117,7 @@ fn resolve_weed_binary() -> Result<PathBuf, String> {
return Ok(local_weed);
}
let bin_dir = env::temp_dir().join("seaweedfs_volume_server_it_bin");
std::fs::create_dir_all(&bin_dir)
.map_err(|e| format!("create binary directory {}: {}", bin_dir.display(), e))?;
let bin_dir = private_bin_dir()?;
let bin_path = bin_dir.join("weed");
if is_executable_file(&bin_path) {
return Ok(bin_path);
@@ -1135,6 +1133,40 @@ fn resolve_weed_binary() -> Result<PathBuf, String> {
Ok(bin_path)
}
// A cached binary under the shared temp dir is only trusted when the
// directory is verifiably private to this user; on unix chmod 0700 fails
// for directories owned by someone else. Otherwise build in a per-process
// directory instead of executing a file another user may have planted.
fn private_bin_dir() -> Result<PathBuf, String> {
let shared = env::temp_dir().join("seaweedfs_volume_server_it_bin");
if make_private_dir(&shared) {
return Ok(shared);
}
let unique = env::temp_dir().join(format!(
"seaweedfs_volume_server_it_bin_{}_{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_millis())
.unwrap_or_default()
));
if make_private_dir(&unique) {
return Ok(unique);
}
Err("unable to create a private binary cache directory".to_string())
}
#[cfg(unix)]
fn make_private_dir(dir: &PathBuf) -> bool {
std::fs::create_dir_all(dir).is_ok()
&& std::fs::set_permissions(dir, std::fs::Permissions::from_mode(0o700)).is_ok()
}
#[cfg(not(unix))]
fn make_private_dir(dir: &PathBuf) -> bool {
std::fs::create_dir_all(dir).is_ok()
}
fn resolve_repo_root() -> Result<PathBuf, String> {
if let Some(from_env) = env::var_os("SEAWEEDFS_REPO_ROOT") {
return Ok(PathBuf::from(from_env));