|
|
Log in / Subscribe / Register

Linux Kernel Runtime Guard reaches its 1.0 release

By Daroc Alden
January 22, 2026

The Linux Kernel Runtime Guard (LKRG) is a out-of-tree loadable kernel module that attempts to detect and report violations of the kernel's internal invariants, such as might be caused by an in-progress security exploit or a rootkit. LKRG has been experimental since its initial release in 2018. In September 2025, the project announced the 1.0 version. With the promises of stability that version brings, users might want more information to decide whether to include it in their kernel.

Security through diversity

LKRG's mission is mildly hopeless — if an attacker has already compromised a running kernel, then there is no theoretical reason that the attacker could not also recognize and block or subvert the LKRG kernel module. In practice, however, an attacker would need to actually know to do that, and do it quickly enough to escape the periodic sweeps that LKRG performs. Using LKRG, therefore, raises the bar for attacks on the Linux kernel.

The project's documentation calls this "security through diversity" — if attackers haven't specifically addressed LKRG, running it can help spot attacks that would otherwise pass unnoticed. Of course, there is a cost to using LKRG as well, which makes the choice of whether to use it a tradeoff.

Running it

LKRG is packaged for Arch, Gentoo, NixOS, and Rocky Linux. On other systems, it can be built from source as a DKMS module. Once loaded, it provides a number of sysctl settings to control exactly what it should check for. LKRG supports two general categories of checks: those on the global state of the kernel and those on the state of a process.

The kernel has a lot of global state; right now, LKRG specifically checks a small but important subset of it. Specifically, it verifies whether code and read-only data within the kernel (including loaded modules) has the right permissions in the page table, whether the code or data has been modified (including whether the global SELinux settings have been tampered with), and some CPU-specific state registers. These last include the Supervisor Mode Execution Protection (SMEP) and Supervisor Mode Access Prevention (SMAP) settings, which prevent kernel code from accessing user-space memory. SMEP prevents the CPU from executing user-space code while in the kernel, and SMAP prevents other accesses. That protection must be disabled when the kernel is deliberately copying data to or from user-space memory, but the rest of the time it prevents an exploit in the kernel from making use of data stored in user space.

The SMEP and SMAP settings are trivial to check, but ensuring that the kernel's data has not been tampered with is more involved. When it first loads, LKRG takes a hash of all the data that should not change and stores this hash in its own memory. Then the data can be periodically re-hashed and checked against the stored hash. Some parts of the kernel can't be covered by the hash, because they do change during normal operation, but can still be checked for consistency against other parts of the kernel. For example, LKRG scans kernel memory to find loaded modules, and compares this to the kernel's own list of loaded modules. If a module is present but not in the list, it is probably trying to hide, and therefore likely to be nefarious. Each kernel module also gets its own hash calculated on first load and then checked periodically.

Kprobes also pose problems: they are dynamically inserted into otherwise-unchanging kernel code. LKRG can't ensure that these changes are correct using a hash, but it can check that the changes only show up when kprobes are actually enabled, and that the "enabled" setting is what it's expected to be.

By default, LKRG checks these global properties at 15-second intervals, but it can be configured to do so more or less frequently, or only when asked to do so. If it does find something suspicious, it can print a log message, restore the previous SELinux "enforcing" setting and SMEP/SMAP state, or panic the kernel.

The other set of checks it runs are per-process. These are also run periodically, but can additionally run just before any process attempts to do some privileged operation. LKRG verifies that the process has the credentials for the operation that it is about to perform, and that the stack pointer (and optionally the frames on the stack) make sense.

Each of these checks can be configured individually, but it is also possible to use LKRG "profiles". It offers several pre-configured levels of detection and enforcement. These range from "detect things only when requested" to "double-check everything whenever possible" (set via the lkrg.profile_validate sysctl) and from "when a violation is detected, log it" to "panic the kernel" (set via the lkrg.profile_enforce sysctl). The default is a reasonable middle ground: check kernel integrity without too much performance overhead, log for suspicious things, and crash the kernel when there's a definite problem.

Is it worth it?

On the one hand, LKRG comes with some admitted downsides: LKRG's default enforcement level is incompatible with running virtual machines VirtualBox; it works fine from within a virtual machine, but causes spurious alarms on the host when the guest CPU has a state that doesn't match the host. [An LKRG maintainer wrote in to point out that the problem exists only on VirtualBox, and that KVM works in the default configuration.] That's not a fundamental limitation of LKRG — it could be extended to track enters and exits from virtual machines, and adjust its expectations accordingly — but it does make it hard to recommend LKRG by default, given how many workloads involve some amount of virtualization.

There is also the matter of performance. A comparison of the Phoronix benchmark suite from 2020 with and without LKRG suggests that it introduced a performance overhead of about 4.4%. Since then, the LKRG developers have gotten this down to around 2.5%, but the error in the measurements makes it hard to be certain of the exact performance penalty, especially since it may be workload-dependent. There is also the fact that, as an out-of-tree module, it does not always support new kernel versions immediately. At the time of writing, it has been tested up through 6.17.0. [The project uses continuous integration testing, and keeps up to date with in-development kernels, but has somewhat infrequent releases.] The project's README suggests that the best use for LKRG would be systems that cannot always update to the latest kernel in response to disclosed vulnerabilities, for whatever reason.

Many users would welcome a small slowdown in the name of security, but there are easier ways to obtain some of the same benefits. For example, the kernel's built-in support for control flow integrity provides much the same benefit as LKRG's stack checking, through well-supported compiler and CPU features. The other things that it validates are less easily replaced, but the kernel has a long history of adopting new built-in ways to protect page-tables. There is always the possibility of bugs in the implementations of these ideas, but it's hard to judge whether LKRG would detect exploitation of those bugs reliably enough to be worthwhile.

On the other hand, the Singularity rootkit has plans to work around LKRG. The Metasploit framework has special code to deal with it and disable exploits that it would detect. It's hard to argue that LKRG is not worth using when it is demonstrably making attackers' lives harder.

Ultimately, LKRG has a relatively niche use case: when the performance overhead is acceptable, the computer's workload doesn't involve virtualization VirtualBox, and the system doesn't run bleeding-edge kernels [or the user is happy to run pre-release versions of LKRG], LKRG can provide defense in depth. Perhaps LKRG's data-validating features will one day make their way into the kernel proper; that does not currently seem to be a priority for the developers. Until LKRG's ideas do make their way into the kernel, users will have to make a judgment call about whether LKRG is right for their use case.



to post comments

vs singularity?

Posted Jan 25, 2026 21:38 UTC (Sun) by MortenSickel (subscriber, #3238) [Link] (2 responses)

Will we soon see a test of LKRG vs Singularity?

vs singularity?

Posted Jan 28, 2026 10:07 UTC (Wed) by tomaxuser (subscriber, #124612) [Link] (1 responses)

My thought also, but it seems Singularity already targets LKRG (https://github.com/MatheuZSecurity/Singularity?tab=readme...) and its author explicitly mentions this in the discussion of the previous LWN article: <https://lwn.net/Articles/1054836/>.

vs singularity?

Posted Jan 30, 2026 6:18 UTC (Fri) by solardiz (guest, #35993) [Link]

LKRG co-maintainer here. I've just formulated our stance on Singularity's bypass, whether it matters (not yet fully relevant under our threat model), and what we're doing about it (anyway), here: https://github.com/lkrg-org/lkrg/issues/455

LKRG _is_ compatible with virtualization, both host and guest, and with bleeding-edge kernels

Posted Feb 5, 2026 5:53 UTC (Thu) by solardiz (guest, #35993) [Link] (2 responses)

Thank you for writing this story, Daroc! We're seeing a spike of interest in LKRG due to Singularity and your story.

Unfortunately, there are some subtle errors in the story, and one that's not subtle: what it says about presumed LKRG incompatibility with virtualization is wrong. LKRG in default configuration runs on most virtualization hosts just fine. In fact, even the LKRG website is currently hosted in a VM on a host that has LKRG loaded.

I can see how you could have arrived at the wrong conclusion by skimming our documentation. We do mention two related compatibility issues. One is limited to VirtualBox hosts only (not something you'd use on a server, and we give a setting to change if you do need to run LKRG on your VirtualBox host, which then works). The other is limited to a non-default configuration of LKRG. In other words, LKRG in default configuration is fully compatible e.g. with a typical KVM and libvirt setup.

Also there's no issue with "bleeding-edge kernels". While LKRG releases are somewhat infrequent and so their documentation (and my 1.0 release announcement from September) doesn't mention the currently latest kernels, we do test with latest in our Continuous Integration setup, and when necessary update our code to be compatible. For example, currently LKRG git is compatible with up to 6.19-rc kernels inclusive (6.19 isn't officially out yet), and the 1.0 release with up to 6.18.y inclusive (these were not out at the time of our release, but we often get lucky like that).

LKRG _is_ compatible with virtualization, both host and guest, and with bleeding-edge kernels

Posted Feb 5, 2026 12:35 UTC (Thu) by daroc (editor, #160859) [Link] (1 responses)

Oh, I see! You're right, I thought that the documented VirtualBox problem extended to other VM setups as well. Do you happen to know what it is about VirtualBox that causes the problem if libvirt doesn't have it?

I'll go poke in corrections to the article.

LKRG _is_ compatible with virtualization, both host and guest, and with bleeding-edge kernels

Posted Feb 5, 2026 18:55 UTC (Thu) by solardiz (guest, #35993) [Link]

As I recall, the VirtualBox host kernel module triggered our pCFI, which suggests their code uses some hack resulting in unexpected kernel stack layout. It could also be that their kernel module was built in a way inconsistent with how the kernel was built, resulting in stack frames or/and unwinding data inconsistent with the kernel build's. We did not investigate this for real - our current suggestion is to relax our pCFI if running on a VirtualBox host. Also, this issue hasn't been re-reported for years, so maybe it was specific to a certain combination of kernel and VirtualBox builds (IIRC, it was only reported by the Whonix maintainer, who then included our workaround), or it's gone by now, or this combination is rare and everyone who has it and would have re-reported it reads our documentation first. Our GitHub issue is https://github.com/lkrg-org/lkrg/issues/82 with no comments added since 2022.


Copyright © 2026, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds