Browse Source

Merge pull request #791 from nrxus/fix-kernel-code-on-submode-gt-255

aya: Fix program loading on kernels with a patch > 255
Tamir Duberstein 1 year ago
parent
commit
67863833ca
2 changed files with 36 additions and 22 deletions
  1. 2 8
      aya/src/programs/mod.rs
  2. 34 14
      aya/src/util.rs

+ 2 - 8
aya/src/programs/mod.rs

@@ -617,14 +617,8 @@ fn load_program<T: Link>(
         },
     ) = obj;
 
-    let target_kernel_version = kernel_version.unwrap_or_else(|| {
-        let KernelVersion {
-            major,
-            minor,
-            patch,
-        } = KernelVersion::current().unwrap();
-        (u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch)
-    });
+    let target_kernel_version =
+        kernel_version.unwrap_or_else(|| KernelVersion::current().unwrap().code());
 
     let prog_name = if let Some(name) = name {
         let mut name = name.clone();

+ 34 - 14
aya/src/util.rs

@@ -49,23 +49,43 @@ impl KernelVersion {
 
     /// Returns the kernel version of the currently running kernel.
     pub fn current() -> Result<Self, impl Error> {
-        let kernel_version = Self::get_kernel_version();
+        Self::get_kernel_version()
+    }
 
-        // The kernel version is clamped to 4.19.255 on kernels 4.19.222 and above.
-        //
-        // See https://github.com/torvalds/linux/commit/a256aac.
-        const CLAMPED_KERNEL_MAJOR: u8 = 4;
-        const CLAMPED_KERNEL_MINOR: u8 = 19;
-        if let Ok(Self {
-            major: CLAMPED_KERNEL_MAJOR,
-            minor: CLAMPED_KERNEL_MINOR,
-            patch: 222..,
-        }) = kernel_version
-        {
-            return Ok(Self::new(CLAMPED_KERNEL_MAJOR, CLAMPED_KERNEL_MINOR, 255));
+    /// The equivalent of LINUX_VERSION_CODE.
+    pub(crate) fn code(self) -> u32 {
+        let Self {
+            major,
+            minor,
+            mut patch,
+        } = self;
+
+        // Certain LTS kernels went above the "max" 255 patch so
+        // backports were done to cap the patch version
+        let max_patch = match (major, minor) {
+            // On 4.4 + 4.9, any patch 257 or above was hardcoded to 255.
+            // See: https://github.com/torvalds/linux/commit/a15813a +
+            // https://github.com/torvalds/linux/commit/42efb098
+            (4, 4 | 9) => 257,
+            // On 4.14, any patch 252 or above was hardcoded to 255.
+            // See: https://github.com/torvalds/linux/commit/e131e0e
+            (4, 14) => 252,
+            // On 4.19, any patch 222 or above was hardcoded to 255.
+            // See: https://github.com/torvalds/linux/commit/a256aac
+            (4, 19) => 222,
+            // For other kernels (i.e., newer LTS kernels as other
+            // ones won't reach 255+ patches) clamp it to 255. See:
+            // https://github.com/torvalds/linux/commit/9b82f13e
+            _ => 255,
+        };
+
+        // anything greater or equal to `max_patch` is hardcoded to
+        // 255.
+        if patch >= max_patch {
+            patch = 255;
         }
 
-        kernel_version
+        (u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch)
     }
 
     // This is ported from https://github.com/torvalds/linux/blob/3f01e9f/tools/lib/bpf/libbpf_probes.c#L21-L101.