diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b66fca86..e48ef590 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -295,11 +295,6 @@ jobs: sudo apt update sudo apt install libpam0g-dev - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - with: - shared-key: "msrv" - - name: Install rust-bindgen uses: taiki-e/install-action@v2 with: diff --git a/src/su/mod.rs b/src/su/mod.rs index 6952640b..3f10e249 100644 --- a/src/su/mod.rs +++ b/src/su/mod.rs @@ -26,7 +26,7 @@ fn authenticate( ) -> Result, Error> { let context = if login { "su-l" } else { "su" }; let use_stdin = true; - let mut pam = PamContext::builder_cli("su", use_stdin, Default::default()) + let mut pam = PamContext::builder_cli("su", use_stdin, false) .target_user(user) .service_name(context) .build()?; diff --git a/src/sudo/mod.rs b/src/sudo/mod.rs index b89b584d..faf0d450 100644 --- a/src/sudo/mod.rs +++ b/src/sudo/mod.rs @@ -25,7 +25,7 @@ mod pipeline; const VERSION: &str = std::env!("CARGO_PKG_VERSION"); -fn candidate_sudoers_file() -> &'static Path { +pub(crate) fn candidate_sudoers_file() -> &'static Path { let pb_rs: &'static Path = Path::new("/etc/sudoers-rs"); if pb_rs.exists() { dev_info!("Running with /etc/sudoers-rs file"); diff --git a/src/system/mod.rs b/src/system/mod.rs index ea521f5f..5120dbcb 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -604,7 +604,7 @@ impl Process { /// attached to the given process pub fn tty_device_id(pid: WithProcess) -> std::io::Result> { // device id of tty is displayed as a signed integer of 32 bits - let data: i32 = read_proc_stat(pid, 6)?; + let data: i32 = read_proc_stat(pid, 6 /* tty_nr */)?; if data == 0 { Ok(None) } else { @@ -619,7 +619,7 @@ impl Process { /// Get the process starting time of a specific process pub fn starting_time(pid: WithProcess) -> io::Result { - let process_start: u64 = read_proc_stat(pid, 21)?; + let process_start: u64 = read_proc_stat(pid, 21 /* start_time */)?; // the startime field is stored in ticks since the system start, so we need to know how many // ticks go into a second @@ -638,7 +638,19 @@ impl Process { } } +/// Read the n-th field (with 0-based indexing) from `/proc//self`. +/// +/// See ["Table 1-4: Contents of the stat fields" of "The /proc +/// Filesystem"][proc_stat_fields] in the Linux docs for all available fields. +/// +/// IMPORTANT: the first two fields are not accessible with this routine. +/// +/// [proc_stat_fields]: https://www.kernel.org/doc/html/latest/filesystems/proc.html#id10 fn read_proc_stat(pid: WithProcess, field_idx: isize) -> io::Result { + // the first two fields are skipped by the code below, and we never need them, + // so no point in implementing code for it in this private function. + debug_assert!(field_idx >= 2); + // read from a specific pid file, or use `self` to refer to our own process let pidref = pid.to_proc_string(); @@ -967,4 +979,17 @@ mod tests { let (_, status) = child_pid.wait(WaitOptions::new()).unwrap(); assert_eq!(status.exit_status(), Some(0)); } + + #[cfg(target_os = "linux")] + #[test] + fn proc_stat_test() { + use super::{read_proc_stat, Process, WithProcess::Current}; + // the process is 'sleeping' (apparently) + assert_eq!("S", read_proc_stat::(Current, 2).unwrap()); + let parent = Process::parent_id().unwrap(); + // field 3 is always the parent process + assert_eq!(parent, read_proc_stat::(Current, 3).unwrap()); + // this next field should always be 0 (which precedes an important bit of info for us!) + assert_eq!(0, read_proc_stat::(Current, 20).unwrap()); + } } diff --git a/src/visudo/mod.rs b/src/visudo/mod.rs index 4aec4abb..05a9f96b 100644 --- a/src/visudo/mod.rs +++ b/src/visudo/mod.rs @@ -11,7 +11,7 @@ use std::{ }; use crate::{ - sudo::diagnostic, + sudo::{candidate_sudoers_file, diagnostic}, sudoers::Sudoers, system::{ can_execute, @@ -64,7 +64,9 @@ pub fn main() { } fn check(file_arg: Option<&str>, perms: bool, owner: bool) -> io::Result<()> { - let sudoers_path = Path::new(file_arg.unwrap_or("/etc/sudoers")); + let sudoers_path = file_arg + .map(Path::new) + .unwrap_or_else(|| candidate_sudoers_file()); let sudoers_file = File::open(sudoers_path) .map_err(|err| io_msg!(err, "unable to open {}", sudoers_path.display()))?; @@ -121,7 +123,9 @@ fn check(file_arg: Option<&str>, perms: bool, owner: bool) -> io::Result<()> { } fn run(file_arg: Option<&str>, perms: bool, owner: bool) -> io::Result<()> { - let sudoers_path = Path::new(file_arg.unwrap_or("/etc/sudoers")); + let sudoers_path = file_arg + .map(Path::new) + .unwrap_or_else(|| candidate_sudoers_file()); let (sudoers_file, existed) = if sudoers_path.exists() { let file = File::options().read(true).write(true).open(sudoers_path)?;