public inbox for openembedded-core@lists.openembedded.org
 help / color / mirror / Atom feed
From: "Sam Kent" <sam.john.kent@gmail.com>
To: openembedded-core@lists.openembedded.org
Cc: Sam Kent <sam.john.kent@gmail.com>
Subject: [PATCH 2/2] oe/package: add unit tests for kernel module detection helpers
Date: Tue, 21 Apr 2026 11:28:45 +0100	[thread overview]
Message-ID: <20260421102845.292954-3-sam.john.kent@gmail.com> (raw)
In-Reply-To: <20260421102845.292954-1-sam.john.kent@gmail.com>

Add unit tests for the filename pre-filter logic, is_kernel_module(),
and the is_kernel_module_signed() detection.

Signed-off-by: Sam Kent <sam.john.kent@gmail.com>
---
 meta/lib/oe/tests/__init__.py     |   0
 meta/lib/oe/tests/test_package.py | 121 ++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)
 create mode 100644 meta/lib/oe/tests/__init__.py
 create mode 100644 meta/lib/oe/tests/test_package.py

diff --git a/meta/lib/oe/tests/__init__.py b/meta/lib/oe/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oe/tests/test_package.py b/meta/lib/oe/tests/test_package.py
new file mode 100644
index 0000000..29e393c
--- /dev/null
+++ b/meta/lib/oe/tests/test_package.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python3
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import mmap
+import os
+import tempfile
+import unittest
+
+
+# Copied from oe/package.py to allow standalone execution without bitbake.
+def is_kernel_module(path):
+    with open(path) as f:
+        return mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ).find(b"vermagic=") >= 0
+
+def is_kernel_module_signed(path):
+    with open(path, "rb") as f:
+        f.seek(-28, 2)
+        module_tail = f.read()
+        return "Module signature appended" in "".join(chr(c) for c in bytearray(module_tail))
+
+
+class TestKernelModuleFilenameFilter(unittest.TestCase):
+    """
+    The pre-filter in process_split_and_strip_files() selects candidates to
+    pass to is_elf(). It must use f.endswith(".ko"), not ".ko" in f, to avoid
+    false-positives on compressed modules (.ko.xz, .ko.gz).
+    """
+
+    ko_files = [
+        "driver.ko",
+        "net/foo.ko",
+    ]
+
+    not_ko_files = [
+        "driver.ko.xz",
+        "driver.ko.gz",
+        "driver.ko2",
+        "myko.c",
+        "vmlinux",
+    ]
+
+    def test_endswith_matches_ko(self):
+        for f in self.ko_files:
+            with self.subTest(f=f):
+                self.assertTrue(f.endswith(".ko"))
+
+    def test_endswith_rejects_non_ko(self):
+        for f in self.not_ko_files:
+            with self.subTest(f=f):
+                self.assertFalse(f.endswith(".ko"))
+
+    def test_old_predicate_had_false_positives(self):
+        # Demonstrate that the previous check (".ko" in f) matched compressed
+        # modules — this is the regression the fix addresses.
+        false_positives = [f for f in self.not_ko_files if ".ko" in f]
+        self.assertEqual(false_positives, ["driver.ko.xz", "driver.ko.gz", "driver.ko2"])
+
+
+class TestIsKernelModule(unittest.TestCase):
+    """
+    is_kernel_module() detects kernel modules by searching for the
+    "vermagic=" string, which is always present in genuine .ko files.
+    """
+
+    def _make_tmp(self, content: bytes) -> str:
+        f = tempfile.NamedTemporaryFile(delete=False, suffix=".ko")
+        f.write(content)
+        f.close()
+        return f.name
+
+    def tearDown(self):
+        # Clean up any temp files created during the test.
+        for attr in ("_tmpfile",):
+            path = getattr(self, attr, None)
+            if path and os.path.exists(path):
+                os.unlink(path)
+
+    def test_detects_vermagic(self):
+        self._tmpfile = self._make_tmp(b"\x7fELF\x00" * 10 + b"vermagic=5.15.0" + b"\x00" * 10)
+        self.assertTrue(is_kernel_module(self._tmpfile))
+
+    def test_rejects_plain_elf(self):
+        self._tmpfile = self._make_tmp(b"\x7fELF\x00" * 50)
+        self.assertFalse(is_kernel_module(self._tmpfile))
+
+
+class TestIsKernelModuleSigned(unittest.TestCase):
+    """
+    is_kernel_module_signed() detects the "Module signature appended" tail
+    that the kernel's modsign infrastructure writes.
+    """
+
+    def _make_tmp(self, content: bytes) -> str:
+        f = tempfile.NamedTemporaryFile(delete=False, suffix=".ko")
+        f.write(content)
+        f.close()
+        return f.name
+
+    def tearDown(self):
+        for attr in ("_tmpfile",):
+            path = getattr(self, attr, None)
+            if path and os.path.exists(path):
+                os.unlink(path)
+
+    def test_detects_signed(self):
+        # Pad to >28 bytes so the seek(-28, 2) works; place the magic at the end.
+        tail = b"Module signature appended\n\x00\x00"
+        self._tmpfile = self._make_tmp(b"\x00" * 64 + tail)
+        self.assertTrue(is_kernel_module_signed(self._tmpfile))
+
+    def test_rejects_unsigned(self):
+        self._tmpfile = self._make_tmp(b"\x7fELF\x00" * 20)
+        self.assertFalse(is_kernel_module_signed(self._tmpfile))
+
+
+if __name__ == "__main__":
+    unittest.main()
-- 
2.34.1



      parent reply	other threads:[~2026-04-21 10:42 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-21 10:28 [PATCH 0/2] Fix .ko file pre-filter to use endswith instead of string contains sam.john.kent
2026-04-21 10:28 ` [PATCH 1/2] package.py: fix kernel module file pre-filter and document strip asymmetry Sam Kent
2026-04-21 10:28 ` Sam Kent [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260421102845.292954-3-sam.john.kent@gmail.com \
    --to=sam.john.kent@gmail.com \
    --cc=openembedded-core@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox