Skip to content

Commit

Permalink
add more Rustified version of kernel_check
Browse files Browse the repository at this point in the history
  • Loading branch information
squell committed Oct 8, 2024
1 parent 8cb08c6 commit 081ea55
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/common/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl fmt::Display for Error {
Error::SelfCheck => {
f.write_str("sudo must be owned by uid 0 and have the setuid bit set")
}
Error::KernelCheck => f.write_str("sudo needs a Kernel >= 5.9"),
Error::KernelCheck => f.write_str("sudo-rs needs a Linux kernel newer than v5.9"),
Error::CommandNotFound(p) => write!(f, "'{}': command not found", p.display()),
Error::InvalidCommand(p) => write!(f, "'{}': invalid command", p.display()),
Error::UserNotFound(u) => write!(f, "user '{u}' not found"),
Expand Down
49 changes: 26 additions & 23 deletions src/system/kernel.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
use std::ffi::CStr;

use std::mem::zeroed;
use std::mem::MaybeUninit;

use crate::common::Error;
use crate::{common::Error, cutils::cerr};

pub fn kernel_check(major: u32, minor: u32) -> Result<(), Error> {
let mut utsname: libc::utsname = unsafe { zeroed() };
#[cfg(target_os = "linux")]
pub fn kernel_check(target_major: u32, target_minor: u32) -> Result<(), Error> {
let mut utsname = MaybeUninit::uninit();

if unsafe { libc::uname(&mut utsname) } != 0 {
// Could not get the kernel version. Try to run anyway
return Ok(());
}

let release = unsafe { CStr::from_ptr(utsname.release.as_ptr()) }
.to_string_lossy()
.into_owned();
// SAFETY: uname is passed a correct pointer
cerr(unsafe { libc::uname(utsname.as_mut_ptr()) })?;

let version_parts: Vec<&str> = release.split('.').collect();
// SAFETY: since uname exited normally, the struct is now initialized
let utsname = unsafe { utsname.assume_init() };

if version_parts.len() < 2 {
// Could not get the kernel version. Try to run anyway
return Ok(());
}
// SAFETY: utsname.release will hold a null-terminated C string
let release = unsafe { CStr::from_ptr(utsname.release.as_ptr()) }.to_string_lossy();

// Parse the major and minor version numbers
if let (Ok(major_version), Ok(minor_version)) = (
version_parts[0].parse::<u32>(),
version_parts[1].parse::<u32>(),
) {
if major_version > major || (major_version == major && minor_version >= minor) {
return Ok(());
let mut version_parts = release.split('.').map_while(|x| x.parse::<u32>().ok());

match (version_parts.next(), version_parts.next()) {
(Some(major), Some(minor)) if (major, minor) < (target_major, target_minor) => {
// We have determined that this Linux kernel is too old.
Err(Error::KernelCheck)
}
_ => {
// We have not been able to prove that sudo-rs is incompatible with this kernel
// and are giving the benefit of the doubt.
Ok(())
}
}
}

#[cfg(not(target_os = "linux"))]
pub fn kernel_check(target_major: u32, target_minor: u32) -> Result<(), Error> {
// if someone managed to compile this on anything else than Linux: your luck runs out here
Err(Error::KernelCheck)
}

0 comments on commit 081ea55

Please sign in to comment.