lkrg-org / lkrg

Linux Kernel Runtime Guard
https://lkrg.org
Other
415 stars 72 forks source link
hardening integrity kernel linux security

Linux Kernel Runtime Guard (LKRG)

LKRG performs runtime integrity checking of the Linux kernel and detection of security vulnerability exploits against the kernel.

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. We currently support kernel versions ranging from as far back as RHEL7's (and its many clones/revisions) and Ubuntu 16.04's to latest mainline and distros' kernels. Our Continuous Integration setup has tested this version of LKRG with up to latest mainline kernel 6.11.0-061100daily20240916-generic as available for Ubuntu on the release date.

LKRG currently supports the x86-64, 32-bit x86, AArch64 (ARM64), and 32-bit ARM CPU architectures.

Please refer to CONCEPTS for concepts behind LKRG and for information on its efficacy, and to PERFORMANCE for information on its performance impact.

The following sections describe how to obtain LKRG sources, build LKRG, test it, install it on the system, and customize its configuration.

Getting the sources

For LKRG releases and latest source code, please refer to its homepage:

https://lkrg.org

To download this release from there and verify it, you would have used commands like the below:

wget https://www.openwall.com/signatures/openwall-offline-signatures.asc
gpg --import openwall-offline-signatures.asc
wget https://lkrg.org/download/lkrg-0.9.9.tar.gz.sign
wget https://lkrg.org/download/lkrg-0.9.9.tar.gz
gpg --verify lkrg-0.9.9.tar.gz.sign lkrg-0.9.9.tar.gz

Please preserve the GnuPG key above and also use it to verify future releases, which will most likely work in a similar manner.

Latest LKRG development source code is hosted on GitHub, from where you can clone the git repository to a local directory using the following command:

git clone https://github.com/lkrg-org/lkrg

Build requirements

To build LKRG, you will need the following software:

For example, under Debian and Ubuntu you can install all of these with:

sudo apt-get install make gcc libelf-dev linux-headers-$(uname -r)

and under Red Hat'ish distributions (e.g. RHEL, CentOS, Fedora) with:

sudo yum install make gcc elfutils-libelf-devel kernel-devel

(For documentation purposes, we prefix commands requiring root access with "sudo", but you may of course run them as root by different means.)

Building

With the above requirements satisfied, you should be able to easily build LKRG by running "make" when you're in LKRG's top level source code directory. Building LKRG does not require root, and thus shouldn't be done as root.

To speed up the building, we recommend specifying a parallel job count matching your machine's logical CPU count, e.g. like this:

make -j8

Testing

We recommend that before you install 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. We also recommend that you keep LKRG's detection of kernel integrity violations enabled for this test, yet change 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.

You can do this for a freshly built LKRG (and while you're still in its top level source code directory) with the following command:

sudo insmod output/lkrg.ko kint_enforce=1

Then check kernel messages for any potential errors, use the system for a long while, and check again:

sudo dmesg

(Depending on kernel version and system configuration, the "dmesg" command might not require root.)

Unload LKRG from the kernel with:

sudo rmmod lkrg

so that it can then be loaded using the same procedure that's used on system bootup and without the parameter override.

Installation

If your Linux distribution uses a supported init system (systemd or OpenRC), you can install LKRG with:

sudo make install

while you're still in its top level source code directory.

We don't in any way favor one init system over another, and would gladly add support for more of them if there's demand, or especially if we receive such contributions. Meanwhile, on a distribution without a supported init system you can let "sudo make install" partially complete (up to the point where it finds you're not using a supported init system).

Run the following command to start the LKRG service, for systemd:

sudo systemctl start lkrg

for OpenRC:

sudo /etc/init.d/lkrg start

for other:

sudo modprobe -v lkrg

Autoload on bootup

In order to automatically load LKRG into the Linux kernel on each bootup run the following command, for systemd:

sudo systemctl enable lkrg

for OpenRC:

sudo rc-update add lkrg boot

for other:

sudo mkdir -p /etc/modules-load.d/ &&
    echo lkrg | sudo tee /etc/modules-load.d/lkrg.conf

Alternatively, you can put the "modprobe lkrg" command into a system startup script. Please note that ideally this command would 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.

Installing using DKMS

DKMS enables kernel modules to be dynamically built for each kernel version. What this means in effect is that on kernel upgrades the module is rebuilt. You can install LKRG using DKMS as well. For instance, on Red Hat'ish distributions after following the shared download instructions above:

sudo tar -xzf lkrg-0.9.9.tar.gz -C /usr/src/
sudo dnf update -y
sudo dnf install kernel-devel dkms openssl
sudo dkms add -m lkrg -v 0.9.9
sudo dkms build -m lkrg -v 0.9.9
sudo dkms install -m lkrg -v 0.9.9

The only difference on other distributions should be the installation of the kernel headers, the DKMS utility, and OpenSSL. Install the headers for the target kernels.

You can then query the status with:

dkms status

If everything is right, you should get similar output to the following:

lkrg/0.9.9, 5.18.9-200.fc36.x86_64, x86_64: installed

Please refer to the previous two sections for how to start the LKRG service or have it started on system bootup. If you wish to use the unit/init file, you must install it manually, e.g., by running the lkrg-bootup.sh script located under scripts/bootup/ with the install subcommand (as root).

Uninstalling

Similarly to installation, you can uninstall LKRG using "make" as well:

sudo make uninstall

while you're in the top level source code directory of the installed version.

If you installed using DKMS, you'd uninstall with:

sudo dkms remove -m lkrg/0.9.9 --all

You can also use the following command to temporarily stop the LKRG service without uninstalling it, for systemd:

sudo systemctl stop lkrg

for OpenRC:

sudo /etc/init.d/lkrg stop

for other:

sudo modprobe -v -r lkrg

Upgrading

Our suggested way to upgrade LKRG is to start by uninstalling the old version.

You can then follow the Testing and Installation steps for the new version.

Recovery

To account for the hopefully unlikely, but really unfortunate event that some incompatibility between the Linux kernel or other components of the system and LKRG isn't detected prior to LKRG installation, yet leads to system crash on bootup, we've included support for the "nolkrg" kernel parameter. Thus, you may disable LKRG by specifying "nolkrg" on the kernel command-line via your bootloader. The system should then boot up without LKRG, and thus without triggering the problem, letting you fix it. You must be aware though, that you will not be able to manually load the LKRG module if the kernel was booted with this parameter.

Module parameters

The LKRG kernel module supports a number of parameters, including kint_enforce already mentioned above and many more.

For freshly built LKRG, you can list the parameters with:

modinfo output/lkrg.ko

while you're still in LKRG's top level source code directory.

With LKRG installed on the system, you can list them with:

sudo modinfo lkrg

(Depending on system configuration, "modinfo" might not require root.)

Parameters can be specified on command-lines of "insmod", "modprobe", or after "options lkrg " in a file in the /etc/modprobe.d directory.

For descriptions of the parameters and their default and possible values, please refer to the following two sections.

Remote logging configuration (load-time only)

LKRG supports the following module parameters (with default values or lack thereof specified in braces) to enable its optional remote logging.

If you're starting LKRG via a systemd unit or startup script (such as those provided in here), our recommended way to specify the above parameters is by creating the file /etc/modprobe.d/lkrg.conf with something like this in it:

options lkrg net_server_addr=127.0.0.1 net_server_pk=64hexdigitshere

Please refer to LOGGING on how to use the corresponding userspace components.

Load-time and runtime configuration

Besides the parameters optionally specified when loading the module into the kernel, LKRG also supports a number of sysctl's, which can be used to adjust its behavior when it is already loaded into the kernel. For each feature that is configurable at both load time and run time, we have a module parameter and a sysctl of similar name (the module parameters lack the "lkrg." prefix, but are otherwise the same), so the below documentation is mostly usable for both.

To list all LKRG sysctl's and their current values, use:

sudo sysctl -a | grep lkrg

The sysctl's are (with default values specified in braces):

That's all for now. Greetings from the LKRG team!