Repository navigation
Test expansion - #23
Merged
Merged
Conversation
The shell script could only grep for a line of output, needed sleeps and sudo gymnastics to sequence things, and left modules loaded when a test failed. tests/harness.py drives kmodleak and parses its report into stacks, allocations and frames so that tests can assert on them directly, and the fixtures in conftest.py build the sample modules as the invoking user, unload whatever a test left behind, and attach dmesg to failures. Run it as root with: sudo python3 -m pytest tests
Tests should not depend on the exact number of stacks in a report or on the names of kernel internals, which vary across kernel versions and with what the kernel allocates on a module's behalf. Report.direct_stacks() finds the allocations made directly by a named module function, with only allocator and tracepoint frames above it, and trace() wraps the load and unload sequence.
The parameter callback allocates after init, from text that stays mapped until unload, so this exercises attribution and symbol resolution from the kallsyms snapshot rather than the in-kernel init symbols. The snapshot is taken when userspace sees the module_load event, which a fast insmod and rmmod can beat, so the variant without a pause is an expected failure until module symbols are resolved in the kernel too.
A private cache cannot be leaked across unload, since kmem_cache_destroy() refuses to destroy a cache with live objects, so the object is held until exit and observed through the report printed on SIGINT.
The module is freed from do_init_module()'s failure path without an exit function, and the kretprobe on load_module() fires after module_free.
insmod leak-dash.ko loads a module named leak_dash, but kmodleak compares the name given on the command line byte for byte.
kfree_rcu() batches the free for up to several seconds, past module_free, and completes it through kmem_cache_free_bulk(), which fires no kfree tracepoint, so kmodleak reports the object as leaked.
The kernel derives a module's name from KBUILD_MODNAME, which replaces dashes in the file name with underscores, and modprobe and rmmod accept either form. kmodleak compared the name byte for byte, so a dashed name never matched the loaded module and the already-loaded check never found it. Also enable the test for it.
module_loaded() took a non-zero core text size as the sign that the traced module had been loaded. A module with no functions outside __init, such as one without an exit function, has an empty MOD_TEXT region on x86, so nothing was ever attributed to it. arm64 hid this because its PLT and ftrace trampoline sections make the region non-empty. Use a flag set by the module_load handler instead, and rename the event pointers in the module handlers that shadowed it. Found by test_leak_from_failing_init in CI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.