Skip to content

Commit 831374d

Browse files
committed
move path_zoneinfo to audit.rs and perform audit checks
1 parent bbc47e7 commit 831374d

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

src/sudo/env/environment.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,14 @@ use std::{
22
collections::{HashMap, HashSet},
33
ffi::{OsStr, OsString},
44
os::unix::prelude::OsStrExt,
5-
path::Path,
65
};
76

87
use crate::common::{CommandAndArguments, Context, Error};
98
use crate::sudoers::Restrictions;
10-
use crate::system::PATH_MAX;
9+
use crate::system::{audit::zoneinfo_path, PATH_MAX};
1110

1211
use super::wildcard_match::wildcard_match;
1312

14-
fn path_zoneinfo() -> Option<&'static str> {
15-
[
16-
"/usr/share/zoneinfo",
17-
"/usr/share/lib/zoneinfo",
18-
"/usr/lib/zoneinfo",
19-
"/usr/lib/zoneinfo",
20-
]
21-
.into_iter()
22-
// Note: We assume that /usr and all contents are only writable by root. If they
23-
// aren't, you can trivially escalate to root anyway.
24-
.find(|p| Path::new(p).exists())
25-
}
26-
2713
// TODO: use _PATH_STDPATH from paths.h
2814
pub(crate) const PATH_DEFAULT: &str = "/usr/bin:/bin:/usr/sbin:/sbin";
2915

@@ -152,7 +138,7 @@ fn is_safe_tz(value: &[u8]) -> bool {
152138
};
153139

154140
if check_value.starts_with(b"/") {
155-
if let Some(path_zoneinfo) = path_zoneinfo() {
141+
if let Some(path_zoneinfo) = zoneinfo_path() {
156142
if !check_value.starts_with(path_zoneinfo.as_bytes())
157143
|| check_value.get(path_zoneinfo.len()) != Some(&b'/')
158144
{
@@ -266,7 +252,7 @@ where
266252

267253
#[cfg(test)]
268254
mod tests {
269-
use super::{is_safe_tz, path_zoneinfo, should_keep};
255+
use super::{is_safe_tz, should_keep, zoneinfo_path};
270256
use std::{collections::HashSet, ffi::OsStr};
271257

272258
struct TestConfiguration {
@@ -328,7 +314,7 @@ mod tests {
328314
#[allow(clippy::bool_assert_comparison)]
329315
#[test]
330316
fn test_tzinfo() {
331-
let path_zoneinfo = path_zoneinfo().unwrap();
317+
let path_zoneinfo = zoneinfo_path().unwrap();
332318
assert_eq!(is_safe_tz("Europe/Amsterdam".as_bytes()), true);
333319
assert_eq!(
334320
is_safe_tz(format!("{path_zoneinfo}/Europe/London").as_bytes()),

src/system/audit.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,20 @@ pub fn secure_open_cookie_file(path: impl AsRef<Path>) -> io::Result<File> {
124124
secure_open_impl(path.as_ref(), &mut open_options, true, true)
125125
}
126126

127+
/// Return the system zoneinfo path after validating that it is safe
128+
pub fn zoneinfo_path() -> Option<&'static str> {
129+
let paths = [
130+
"/usr/share/zoneinfo",
131+
"/usr/share/lib/zoneinfo",
132+
"/usr/lib/zoneinfo",
133+
];
134+
135+
paths.into_iter().find(|p| {
136+
let path = Path::new(p);
137+
dbg!(path.metadata()).and_then(|meta| checks(path, meta)).is_ok()
138+
})
139+
}
140+
127141
fn checks(path: &Path, meta: Metadata) -> io::Result<()> {
128142
let error = |msg| Error::new(ErrorKind::PermissionDenied, msg);
129143

0 commit comments

Comments
 (0)