LKRG: a kernel module that watches the kernel for tampering
Linux Kernel Runtime Guard
At a glance
- What is it?
- Linux Kernel Runtime Guard is a loadable kernel module that performs runtime integrity checking of the Linux kernel and detects exploits against it, built rather than patched so it loads on top of a wide range of mainline and distribution kernels. It suits an operator who wants tamper detection on a machine they cannot rebuild, and it runs with kernel panic as its default enforcement action.
- Who is it for?
- LKRG fits an operator who needs kernel integrity monitoring on a machine they cannot recompile, and it does not fit a kernel developer working on a custom kernel, where the patch route is better, or a virtualised environment where the hypervisor already provides tamper evidence.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A module, not a patch, and why that choice drives everything else
Linux Kernel Runtime Guard, LKRG, performs runtime integrity checking of the Linux kernel and detection of security vulnerability exploits against the kernel.
The design decision that shapes the whole project is stated up front. LKRG is a kernel module, not a kernel patch, so it can be built for and loaded on top of a wide range of mainline and distros kernels, without needing to patch those.
That distinction has practical consequences. A kernel patch requires a source tree, a build of the kernel itself, and a reboot into a kernel you have recompiled, which on a distribution machine means maintaining your own kernel packages. A module is built against the running kernel's build directory and loaded with insmod, so the same source produces a module for whichever kernel the machine happens to run. The support range is broad, from as far back as RHEL7's and its many clones and revisions to latest mainline and distribution kernels, and LKRG 1.0.1 has been tested with kernels from RHEL/CentOS 7's 3.10.0-1160 and up to Fedora's build of 7.0.0-62.fc45.x86_64.
The architecture support is x86-64, 32-bit x86, AArch64 and 32-bit ARM.
Two documents in the repository do the explanatory work. The README points to CONCEPTS for the concepts behind LKRG and for information on its efficacy, and to PERFORMANCE for information on its performance impact. Neither is reproduced in the README, which is deliberate, and both are where the real assessment information lives.
The licence is recorded as a custom one that GitHub cannot classify, with the terms in the LICENSE file, and the repository also carries a PATREONS file, a CHANGES file, a LOGGING file, and packaging for Debian, a spec file for RPM distributions and a dkms.conf.
The last push was on 2026-09-25 and the repository has no GitHub releases, so the versions that matter are the ones named in the README, currently 1.0.1.
Getting the source, and verifying it with the OpenPGP signature
The README is unusually careful about how you obtain the code, and the reason is that a kernel module runs with the highest privilege on the machine.
For LKRG releases and latest source code, the README points at its homepage at lkrg.org. The development source code is hosted on GitHub, and can be cloned to a local directory.
git clone https://github.com/lkrg-org/lkrgThe release download comes with a signature, and the verification sequence is spelled out in full.
wget https://www.openwall.com/signatures/openwall-offline-signatures.asc
gpg --import openwall-offline-signatures.asc
wget https://lkrg.org/download/lkrg-1.0.1.tar.gz.sign
wget https://lkrg.org/download/lkrg-1.0.1.tar.gz
gpg --verify lkrg-1.0.1.tar.gz.sign lkrg-1.0.1.tar.gzThe instructions say to preserve the GnuPG key above and also use it to verify future releases, which will most likely work in a similar manner.
That is the right instruction to follow for a component that runs inside the kernel. A kernel module built from a tarball fetched over HTTPS and installed with insmod is code that can subvert the operating system, and the verification step is what separates a supply chain from a trust problem. The openwall signature is the project's own mechanism for this, and it is a deliberate design choice rather than a build artifact.
The project also ships a debian directory, an lkrg.spec file for RPM distributions, and a dkms.conf, so distribution packaging exists alongside the source release. The mkosi.build, mkosi.default and mkosi.postinst files suggest reproducible image building as well, which is consistent with a project whose output is security sensitive.
Building it, and the toolchain detail that costs people an afternoon
The build requirements are short, and one of them is stricter than it looks.
You need GNU make, GCC, and ideally the same version of it that was used to build the kernel itself, with the README noting that some people manage with clang, but that this is unsupported, so expect issues. You also need awk, as needed by recent Linux kernel Makefile, libelf including its development sub-package in case your target kernel was built with CONFIG_UNWINDER_ORC=y, and a kernel build directory corresponding to the Linux kernel image the module is to run on.
The distribution packages are given for the main families.
sudo apt-get install make gcc gawk libelf-dev linux-headers-$(uname -r) sudo dnf install make gcc gawk elfutils-libelf-devel kernel-develOlder Red Hat style systems need the older package names, openSUSE has its own list, and Arch has a fourth.
sudo zypper -n install make gcc awk kernel-default-devel sudo pacman -S make gcc awk libelf linux-headersThe GCC point is the one that generates the most support questions, and it is not pedantry. A kernel module is compiled against the kernel headers and with the same compiler expectations, and a mismatch produces symbol errors that look like a broken build rather than a version problem. The README's phrasing, ideally the same version of it that was used to build the kernel itself, is a hint that this matters more than it first appears.
Once the requirements are in place the build is one command in the top level source directory, and it does not require root, and thus shouldn't be done as root. To speed the building, the README recommends specifying a parallel job count matching your machine's logical CPU count.
make -j8Testing by loading it once, with the panic turned into a log line
The testing section is the most important part of the README for anyone about to put this on a machine they care about, and the procedure is deliberate.
The recommendation is that before installing LKRG on the system such that it would be started on bootup, you manually test loading the LKRG module into the kernel without making the setup permanent. The README also recommends keeping LKRG's detection of kernel integrity violations enabled for this test, yet changing its enforcement action from kernel panic, the default, to mere logging. This way you can safely detect potential system-specific false positives and only proceed with installation if there are none.
The module is loaded with the enforcement parameter spelled out.
sudo insmod lkrg.ko kint_enforce=1Then you check the kernel messages for any potential errors, use the system for a while, and check again. Depending on kernel version and system configuration, the dmesg command might not require root.
sudo dmesgUnloading the module reverses the test, and the README is explicit about the point of doing so.
sudo rmmod lkrgIt says to do that so that it can then be loaded using the same procedure that's used on system bootup and without the parameter override.
The logic here is sound and it generalises beyond LKRG. A detector that responds to a violation by panicking the kernel will, on a machine with a false positive, take the machine down. Running the detector in log-only mode first converts an availability risk into a report, and the report is what tells you whether the detector is configured correctly for this kernel and this workload. The cost is a window in which the kernel is unprotected, and the benefit is not finding out the hard way.
Installing it, and the two boot mechanisms
If your Linux distribution uses a supported init system, systemd or OpenRC, you can install LKRG with make install, while you are still in its top level source code directory.
sudo make installThe project says it does not in any way favor one init system over another, and would gladly add support for more of them if there is demand, or especially if it receives such contributions. Meanwhile, on a distribution without a supported init system you can let make install partially complete, up to the point where it finds you are not using a supported init system.
Starting the service is then a per-init-system command.
sudo systemctl start lkrg sudo /etc/init.d/lkrg start sudo modprobe -v lkrgThe third is the fallback for everything else, and it is also the one to understand if you want control over load ordering. The autoload on bootup section says the modprobe lkrg command should ideally run before sysctl files, especially /etc/sysctl.d/01-lkrg.conf, are processed, or otherwise the LKRG settings specified in those would not take effect. That ordering constraint is a real detail, because LKRG's own configuration is delivered through sysctl, and a module loaded after sysctl has run will apply different settings than the one intended.
For systemd the autoload command is systemctl enable lkrg, for OpenRC it is rc-update add lkrg boot, and for anything else you write a modules-load.d file.
sudo rc-update add lkrg boot sudo mkdir -p /etc/modules-load.d/ &&
echo lkrg | sudo tee /etc/modules-load.d/lkrg.confThe README notes that alternatively you can put the modprobe lkrg command into a system startup script.
DKMS, and the case for letting the kernel upgrade rebuild the module
The DKMS path exists because kernel modules are tied to the kernel they were built against, and a distribution that upgrades its kernel breaks every out-of-tree module built for the old one.
DKMS enables kernel modules to be dynamically built for each kernel version, and what this means in effect is that on kernel upgrades the module is rebuilt. The README gives the full sequence for Red Hat style distributions, following the shared download instructions.
sudo tar -xzf lkrg-1.0.1.tar.gz -C /usr/src/
sudo dnf update -y
sudo dnf install kernel-devel dkms openssl
sudo dkms add -m lkrg -v 1.0.1
sudo dkms build -m lkrg -v 1.0.1
sudo dkms install -m lkrg -v 1.0.1The only difference on other distributions should be the installation of the kernel headers, the DKMS utility, and OpenSSL. The headers are installed for the target kernels.
The status is then queried with dkms status, and the expected output looks like this.
dkms status lkrg/1.0.1, 5.18.9-200.fc36.x86_64, x86_64: installedThat single line shows the three things worth tracking: the module version, the kernel it was built for, and the architecture. When a kernel upgrade changes the middle column, the module has been rebuilt for the new kernel, and that is the whole point of the DKMS route.
The tradeoff is build time and a dependency on the distribution's kernel packages staying available. A distribution that ships a new kernel and then removes the old headers breaks DKMS builds for the old kernel, which is why the tarball route and the DKMS route are both documented rather than one being recommended outright.
The Makefile also shows a build detail that reflects the project's security focus. In a debug build the compile flags include -finstrument-functions, and in a release build those trace-related flags are filtered out so that ftrace cannot probe LKRG's own functions, with a comment explaining that this removes even more code transformations than specifying notrace on every function. The Makefile also keeps a deliberately instrumented dummy function so the kprobes it installs on itself can be verified.
Editorial conclusion
LKRG fits an operator who needs kernel integrity monitoring on a machine they cannot recompile, and it does not fit a kernel developer working on a custom kernel, where the patch route is better, or a virtualised environment where the hypervisor already provides tamper evidence. Before enabling it permanently, load it once by hand with kint_enforce=1 and watch the kernel log, because the default enforcement action is a kernel panic and the README asks you to detect possible system-specific false positives before you install it on bootup.
Frequently asked questions
What does LKRG actually do?
It performs runtime integrity checking of the Linux kernel and detection of security vulnerability exploits against the kernel. It is a loadable kernel module rather than a kernel patch, so it can be built for and loaded on top of a wide range of mainline and distribution kernels without patching them.
How do I test LKRG before installing it permanently?
Load the module by hand with sudo insmod lkrg.ko kint_enforce=1, which keeps detection of kernel integrity violations enabled but changes the enforcement action from the default kernel panic to logging. Then check sudo dmesg after using the system for a while, and unload it with sudo rmmod lkrg.
What does DKMS do for an LKRG installation?
DKMS enables kernel modules to be dynamically built for each kernel version, so on kernel upgrades the module is rebuilt. The status is checked with dkms status, which shows the module version, the kernel it was built for and the architecture.
Which compilers and packages does building LKRG need?
You need GNU make, GCC ideally at the same version used to build the kernel itself, with clang unsupported, awk, libelf with its development sub-package for kernels built with CONFIG_UNWINDER_ORC=y, and a kernel build directory for the kernel the module will run on. The README gives the install command for Debian and Ubuntu, Red Hat style, openSUSE and Arch.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lkrg-org-lkrg)Was this useful?