Преглед изворни кода

Merge pull request #579 from marysaka/fix/ubuntu-debian-kernel-version-code

aya: Correctly set the kernel code version for Ubuntu and Debian kernel
Alessandro Decina пре 1 година
родитељ
комит
1066c6c2e5
1 измењених фајлова са 61 додато и 0 уклоњено
  1. 61 0
      aya/src/sys/mod.rs

+ 61 - 0
aya/src/sys/mod.rs

@@ -8,6 +8,8 @@ mod fake;
 use std::io;
 #[cfg(not(test))]
 use std::{ffi::CString, mem};
+#[cfg(not(test))]
+use std::{fs::File, io::Read};
 
 #[cfg(not(test))]
 use libc::utsname;
@@ -82,8 +84,40 @@ pub(crate) fn kernel_version() -> Result<(u32, u32, u32), ()> {
     Ok((0xff, 0xff, 0xff))
 }
 
+#[cfg(not(test))]
+fn ubuntu_kernel_version() -> Result<(u32, u32, u32), ()> {
+    if let Ok(mut file) = File::open("/proc/version_signature") {
+        let mut buf = String::new();
+        let mut major = 0u32;
+        let mut minor = 0u32;
+        let mut patch = 0u32;
+        let format = CString::new("%*s %*s %u.%u.%u\n").unwrap();
+
+        file.read_to_string(&mut buf).map_err(|_| ())?;
+
+        unsafe {
+            if libc::sscanf(
+                buf.as_ptr() as *const _,
+                format.as_ptr(),
+                &mut major as *mut u32,
+                &mut minor as *mut _,
+                &mut patch as *mut _,
+            ) == 3
+            {
+                return Ok((major, minor, patch));
+            }
+        }
+    }
+
+    Err(())
+}
+
 #[cfg(not(test))]
 pub(crate) fn kernel_version() -> Result<(u32, u32, u32), ()> {
+    if let Ok(version) = ubuntu_kernel_version() {
+        return Ok(version);
+    }
+
     unsafe {
         let mut v = mem::zeroed::<utsname>();
         if libc::uname(&mut v as *mut _) != 0 {
@@ -93,6 +127,33 @@ pub(crate) fn kernel_version() -> Result<(u32, u32, u32), ()> {
         let mut major = 0u32;
         let mut minor = 0u32;
         let mut patch = 0u32;
+
+        let debian_marker = CString::new("Debian").unwrap();
+
+        let p = libc::strstr(v.version.as_ptr(), debian_marker.as_ptr());
+
+        if !p.is_null() {
+            let debian_format = CString::new("Debian %u.%u.%u").map_err(|_| ())?;
+
+            if libc::sscanf(
+                p,
+                debian_format.as_ptr(),
+                &mut major as *mut u32,
+                &mut minor as *mut _,
+                &mut patch as *mut _,
+            ) == 3
+            {
+                // On Debian 10, kernels after 4.19.229 expect 4.19.255 due to broken Makefile patches.
+                let patch_level_limit = if major == 4 && minor == 19 { 230 } else { 255 };
+
+                if patch >= patch_level_limit {
+                    patch = 255;
+                }
+
+                return Ok((major, minor, patch));
+            }
+        }
+
         let format = CString::new("%u.%u.%u").unwrap();
         if libc::sscanf(
             v.release.as_ptr(),