Skip to content

Commit bdca27b

Browse files
committed
Factor enforce_hardened_tree out of fix_config_permissions.
1 parent 4017631 commit bdca27b

1 file changed

Lines changed: 49 additions & 35 deletions

File tree

cmd/soroban-cli/src/config/locator.rs

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -574,52 +574,66 @@ impl Pwd for Args {
574574
}
575575
}
576576

577-
#[cfg(unix)]
578-
fn fix_config_permissions(root: std::path::PathBuf) {
579-
use std::os::unix::fs::PermissionsExt;
580-
581-
let mut bad_dirs = Vec::new();
582-
let mut bad_files = Vec::new();
583-
let mut stack = vec![root];
584-
585-
while let Some(dir) = stack.pop() {
586-
if let Ok(meta) = std::fs::metadata(&dir) {
587-
if meta.permissions().mode() & 0o777 != 0o700 {
588-
bad_dirs.push(dir.clone());
577+
/// Walk `root` recursively. For every regular entry whose permissions don't
578+
/// already match the hardened mode (0o700 for dirs, 0o600 for files), set
579+
/// them. Returns the dirs and files that were changed so callers can decide
580+
/// whether to surface a warning. Symlinks are skipped — mode bits aren't
581+
/// meaningful for them and `set_permissions` would follow them.
582+
///
583+
/// On non-unix platforms this is a no-op; tempdirs / config dirs there rely
584+
/// on filesystem ACLs created by the higher-level APIs.
585+
#[allow(clippy::unnecessary_wraps)]
586+
pub(crate) fn enforce_hardened_tree(root: &Path) -> io::Result<(Vec<PathBuf>, Vec<PathBuf>)> {
587+
#[cfg(unix)]
588+
{
589+
use std::os::unix::fs::PermissionsExt;
590+
let mut changed_dirs = Vec::new();
591+
let mut changed_files = Vec::new();
592+
let mut stack = vec![root.to_path_buf()];
593+
while let Some(p) = stack.pop() {
594+
let Ok(meta) = std::fs::symlink_metadata(&p) else {
595+
continue;
596+
};
597+
if meta.file_type().is_symlink() {
598+
continue;
589599
}
590-
}
591-
592-
if let Ok(entries) = std::fs::read_dir(&dir) {
593-
for entry in entries.filter_map(Result::ok) {
594-
let path = entry.path();
595-
596-
if path.is_dir() {
597-
stack.push(path);
598-
} else if let Ok(meta) = std::fs::metadata(&path) {
599-
if meta.permissions().mode() & 0o777 != 0o600 {
600-
bad_files.push(path);
600+
let current = meta.permissions().mode() & 0o777;
601+
if meta.is_dir() {
602+
if current != 0o700 {
603+
set_hardened_permissions(&p)?;
604+
changed_dirs.push(p.clone());
605+
}
606+
if let Ok(entries) = std::fs::read_dir(&p) {
607+
for entry in entries.filter_map(Result::ok) {
608+
stack.push(entry.path());
601609
}
602610
}
611+
} else if current != 0o600 {
612+
set_hardened_permissions(&p)?;
613+
changed_files.push(p);
603614
}
604615
}
616+
Ok((changed_dirs, changed_files))
605617
}
618+
#[cfg(not(unix))]
619+
{
620+
let _ = root;
621+
Ok((Vec::new(), Vec::new()))
622+
}
623+
}
606624

607-
let print = Print::new(false);
625+
#[cfg(unix)]
626+
fn fix_config_permissions(root: std::path::PathBuf) {
627+
let Ok((dirs, files)) = enforce_hardened_tree(&root) else {
628+
return;
629+
};
608630

609-
if !bad_dirs.is_empty() {
631+
let print = Print::new(false);
632+
if !dirs.is_empty() {
610633
print.warnln("Updated config directories permissions to 0700.");
611-
612-
for dir in bad_dirs {
613-
let _ = set_hardened_permissions(&dir);
614-
}
615634
}
616-
617-
if !bad_files.is_empty() {
635+
if !files.is_empty() {
618636
print.warnln("Updated config files permissions to 0600.");
619-
620-
for file in bad_files {
621-
let _ = set_hardened_permissions(&file);
622-
}
623637
}
624638
}
625639

0 commit comments

Comments
 (0)