@@ -37,13 +37,22 @@ impl RuntimePaths { |
| 37 | } | 37 | } |
| 38 | | 38 | |
| 39 | pub fn ensure_runtime_dir(&self) -> io::Result<()> { | 39 | pub fn ensure_runtime_dir(&self) -> io::Result<()> { |
| 40 | - fs::create_dir_all(&self.root) | 40 | + fs::create_dir_all(&self.root)?; |
| | 41 | + #[cfg(unix)] |
| | 42 | + { |
| | 43 | + use std::os::unix::fs::PermissionsExt; |
| | 44 | + |
| | 45 | + fs::set_permissions(&self.root, fs::Permissions::from_mode(0o700))?; |
| | 46 | + } |
| | 47 | + Ok(()) |
| 41 | } | 48 | } |
| 42 | } | 49 | } |
| 43 | | 50 | |
| 44 | #[cfg(test)] | 51 | #[cfg(test)] |
| 45 | mod tests { | 52 | mod tests { |
| | 53 | + use std::fs; |
| 46 | use std::path::PathBuf; | 54 | use std::path::PathBuf; |
| | 55 | + use std::time::{SystemTime, UNIX_EPOCH}; |
| 47 | | 56 | |
| 48 | use super::RuntimePaths; | 57 | use super::RuntimePaths; |
| 49 | | 58 | |
@@ -64,4 +73,28 @@ mod tests { |
| 64 | PathBuf::from("/tmp/runtime/garwarp/requests.state") | 73 | PathBuf::from("/tmp/runtime/garwarp/requests.state") |
| 65 | ); | 74 | ); |
| 66 | } | 75 | } |
| | 76 | + |
| | 77 | + #[cfg(unix)] |
| | 78 | + #[test] |
| | 79 | + fn ensure_runtime_dir_sets_private_permissions() { |
| | 80 | + use std::os::unix::fs::PermissionsExt; |
| | 81 | + |
| | 82 | + let nanos = SystemTime::now() |
| | 83 | + .duration_since(UNIX_EPOCH) |
| | 84 | + .map_or(0, |duration| duration.as_nanos()); |
| | 85 | + let base = std::env::temp_dir().join(format!("garwarp-runtime-test-{nanos}")); |
| | 86 | + let paths = RuntimePaths::from_base(base.clone()); |
| | 87 | + paths |
| | 88 | + .ensure_runtime_dir() |
| | 89 | + .expect("runtime dir should be created"); |
| | 90 | + |
| | 91 | + let mode = fs::metadata(&paths.root) |
| | 92 | + .expect("runtime metadata should be readable") |
| | 93 | + .permissions() |
| | 94 | + .mode() |
| | 95 | + & 0o777; |
| | 96 | + assert_eq!(mode, 0o700); |
| | 97 | + |
| | 98 | + fs::remove_dir_all(base).expect("temp runtime dir should be removed"); |
| | 99 | + } |
| 67 | } | 100 | } |