Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remote logging #302

Merged
merged 31 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cbfacf1
Net: Initial integration of log message delivery
solardiz Oct 26, 2022
04b329a
Net: Add message sending timestamps
solardiz Nov 5, 2022
57a8cf8
Net: Implement replay protection within TCP streams
solardiz Nov 10, 2022
f6d52c9
Net: Resend the unsent message upon reconnect
solardiz Nov 10, 2022
1b2b7cf
Net: Allow to exclude this functionality at compile time
solardiz Nov 28, 2022
cce44d9
Net: Log configuration errors
solardiz Nov 28, 2022
2daca74
Net: Log connection errors (rate-limited)
solardiz Nov 28, 2022
972f195
Net: Rate-limit reconnect attempts
solardiz Nov 28, 2022
e55841c
Net: Linux 6.3+ support
solardiz Feb 17, 2024
0c5ba4e
Net: Clean up hydrogen/impl/random.h
solardiz Feb 17, 2024
4536c68
Net: Add authorship, copyright, and license statements
solardiz Feb 18, 2024
457f9a1
Hydrogen: Add random/unix.h
solardiz Feb 18, 2024
9c48cdd
Logger: Initial commit
solardiz Nov 10, 2022
8e6087c
Logger: Implement replay protection within TCP streams
solardiz Nov 10, 2022
c0c3ec7
Logger: Add receive timestamps
solardiz Nov 17, 2022
7bd8825
Logger: Include receive timestamps into the same write(2) with message
solardiz Nov 24, 2022
613f90c
Logger: Add basic syntax checking of decrypted received messages
solardiz Nov 24, 2022
b0402dd
Logger: Add log file parser/reporter
solardiz Nov 24, 2022
fb644c7
Logger: Add authorship, copyright, and license statements
solardiz Feb 18, 2024
57b4ae4
Logger: Derive PK from SK
solardiz Feb 21, 2024
265964b
Net, Logger: Add documentation
solardiz Feb 25, 2024
2fdd45a
Logger: Daemonize itself
solardiz Feb 26, 2024
6ce7e3e
Logger: Store logs under /var/log/lkrg-logger
solardiz Feb 26, 2024
091f0bf
Net, Logger: Use port 514/tcp by default
solardiz Feb 26, 2024
f7f2a93
Logger: Drop root
solardiz Feb 26, 2024
02e38fe
Logger: Run with umask 077
solardiz Feb 26, 2024
011e12d
Logger: Add "make install" and "make uninstall"
solardiz Feb 26, 2024
11dee92
Logger: Support the -D option to disable daemonization
solardiz Feb 26, 2024
90ba51d
Logger: Add systemd service
solardiz Feb 27, 2024
6315698
Net: README: Add example usage of /etc/modprobe.d/lkrg.conf
solardiz Feb 27, 2024
addb229
RPM: Add logger sub-package, prepare for 0.9.8
solardiz Feb 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
The following major changes have been made since LKRG 0.9.7:

*) Add optional remote kernel message logging, including the sending component
in LKRG itself and the receiving/logging counterpart in a userspace daemon,
as well as additional utilities to generate a public/secret keypair and to
process the logs, and documentation in LOGGING
*) Add support for RHEL 8.8+
*) RPM spec file improvements to make it work or properly fail in a wider set
of circumstances, and to use the "weak-modules" script if available so that
Expand Down
9 changes: 8 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
Linux Kernel Runtime Guard (LKRG)
Copyright (c) 2015-2023 Adam 'pi3' Zabrocki
Copyright (c) 2020-2022 Mariusz Zaborski
Copyright (c) 2020-2023 Solar Designer
Copyright (c) 2020-2024 Solar Designer

src/modules/net/net.*, logger
Copyright (c) 2022 Binarly
Copyright (c) 2024 Solar Designer

src/modules/net/hydrogen/*
Copyright (c) 2017-2022 Frank Denis

scripts/copy-builtin.sh, scripts/add-exports.sh
Copyright (c) 2021-2022 RageLtMan
Expand Down
123 changes: 123 additions & 0 deletions LOGGING
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
LKRG remote logging
===================

LKRG supports optional remote kernel message logging. Once enabled, this logs
not only messages generated by LKRG, but also all other kernel messages.

The sending component is in the LKRG kernel module itself, whereas the
receiving and logging counterpart is in a userspace daemon. There are also
additional userspace utilities.


Transport security
------------------

We currently use a one-way TCP stream, with transport security provided by our
usage of libhydrogen (bundled in here). libhydrogen is "built using just two
cryptographic building blocks: the Curve25519 elliptic curve, and the Gimli
permutation." It implements a number of Noise protocol handshake patterns, out
of which we currently use the most trivial one, "N".

As long as the server's secret key is not compromised, this protects
confidentiality and integrity of messages. While our usage of a one-way TCP
stream (a write-only socket) is a great way to limit LKRG's remote attack
surface, it precludes implementation of forward secrecy, so a compromised
secret key can unfortunately be used to decrypt past sessions.

Replay protection is partial - messages from the middle of a (current or past)
TCP connection cannot be replayed on their own (won't be accepted by the
receiver even if the TCP layer is tricked to accept them), but an entire TCP
connection or its starting portion can be.

There's no explicit server authentication since the communication on top of TCP
is one-way, however security against a spoofed/MITM server is achieved through
the client only encrypting to the correct server's pre-configured public key.

There's currently no explicit client authentication (a major shortcoming to be
addressed), but only clients with knowledge of the server's public key can send
messages that would be accepted by the server.


How to use
----------

Please refer to the section "Remote logging configuration" in README for how to
enable remote logging in LKRG.

Please read below about the userspace tools to support LKRG remote logging.


Build requirements and building
-------------------------------

The build requirements for the userspace tools are a subset of what's needed to
build LKRG itself. Currently, it's just GNU make and GCC. You can build the
tools by simply running "make" in the "logger" directory, e.g. like this:

make -C logger -j8

This will build three programs described below.


Installation
------------

To install the programs on the system globally, run:

sudo make install

On systems with systemd, this also installs, but does not yet enable, a systemd
unit file for lkrg-logger.


Uninstalling
------------

Similarly to installation, you can uninstall these programs and the systemd
unit file with:

sudo make uninstall


lkrg-keygen
-----------

Run this program once to obtain a public/secret keypair, which it prints as:

LKRG_LOGGER_PK=64hexdigitshere
LKRG_LOGGER_SK=64hexdigitshere

Use the 64 digits from LKRG_LOGGER_PK as value for LKRG's net_server_pk module
parameter. Use the line LKRG_LOGGER_SK= including the 64 digits to set an
environment variable of this name for lkrg-logger.


lkrg-logger
-----------

This is the receiving and logging userspace daemon. Currently, it is to be set
up and started via systemd like this:

useradd -r lkrg-logger -d / -s /sbin/nologin
mkdir /var/log/lkrg-logger
chown lkrg-logger: /var/log/lkrg-logger

umask 077
lkrg-keygen > /etc/lkrg-logger.conf
systemctl enable lkrg-logger
systemctl start lkrg-logger

or instead of the last 4 commands above, started manually as root like this:

LKRG_LOGGER_SK=64hexdigitshere lkrg-logger

Per-client log files will appear in the log directory once client connections
encrypting to the right public key arrive. The filenames correspond to each
client's IPv4 address as seen by the server.


lkrg-logctl
-----------

A tool to process one lkrg-logger output file. This program currently derives
each event's ISO timestamp from several recorded relative timestamps.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ $(TARGET)-objs += src/modules/ksyms/p_resolve_ksym.o \
src/modules/integrity_timer/p_integrity_timer.o \
src/modules/integrity_timer/verify_kprobes/p_verify_kprobes.o \
src/modules/kmod/p_kmod.o \
src/modules/net/net.o \
src/modules/database/CPU.o \
src/modules/database/arch/x86/p_x86_metadata.o \
src/modules/database/arch/x86/p_switch_idt/p_switch_idt.o \
Expand Down
34 changes: 29 additions & 5 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,39 @@ With LKRG installed on the system, you can list them with:

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

Parameters can be specified on command-lines of "insmod", "modprobe", or in a
file in the /etc/modprobe.d directory.
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 section.
please refer to the following two sections.


Runtime configuration
---------------------
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.

- net_server_addr (no default)
Log server IPv4 address (e.g., 127.0.0.1)

- net_server_port (514)
Log server TCP port number

- net_server_pk (no default)
Log server public key (64 hexadecimal digits)

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
Expand Down
11 changes: 10 additions & 1 deletion debian/copyright
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@ Source: https://lkrg.org
Files: *
Copyright: 2015-2023 Adam 'pi3' Zabrocki <[email protected]>
2020-2022 Mariusz Zaborski
2020-2023 Solar Designer
2020-2024 Solar Designer
License: GPL-2.0

Files: src/modules/net/net.*
Copyright: 2022 Binarly
2024 Solar Designer
License: GPL-2.0

Files: src/modules/net/hydrogen/*
Copyright: 2017-2022 Frank Denis
License: ISC or GPL-2.0

Files: debian/*
Copyright: 2020-2021 Mikhail Morfikov <[email protected]>
License: GPL-2.0
Expand Down
43 changes: 38 additions & 5 deletions lkrg.spec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
%define kmod_headers_version %(rpm -qa kernel-devel | sed 's/^kernel-devel-//' | sort -r | head -1)
%define kmod_headers_version %(rpm -qa kernel-devel | sed 's/^kernel-devel-//' | sort -rV | head -1)
%define module_dir /lib/modules/%kmod_headers_version/extra
%global debug_package %nil

Summary: Linux Kernel Runtime Guard (LKRG)
Name: lkrg
Version: 0.9.7
Release: 3%{?dist}
Version: 0.9.8
Release: 1%{?dist}
License: GPLv2
URL: https://lkrg.org
Source: https://lkrg.org/download/%name-%version.tar.gz
Expand All @@ -24,17 +24,27 @@ processes (exploit detection). For process credentials, LKRG attempts to
detect the exploit and take action before the kernel would grant access (such
as open a file) based on the unauthorized credentials.

%package logger
Summary: Linux Kernel Runtime Guard (LKRG) remote logging tools
Requires(pre): /usr/sbin/useradd

%description logger
Userspace tools to support Linux Kernel Runtime Guard (LKRG) remote logging.

%prep
%setup -q

%build
make %{?_smp_mflags} KERNELRELEASE=%kmod_headers_version
make -C logger %{?_smp_mflags} CFLAGS='%optflags'

%install
rm -rf %buildroot
install -D -p -m 644 lkrg.ko %buildroot%module_dir/lkrg.ko
install -D -p -m 644 scripts/bootup/systemd/lkrg.service %buildroot%_unitdir/lkrg.service
install -D -p -m 644 scripts/bootup/lkrg.conf %buildroot%_sysconfdir/sysctl.d/01-lkrg.conf
make -C logger install DESTDIR=%buildroot PREFIX=/usr UNITDIR=%_unitdir
mkdir -p %buildroot/var/log/lkrg-logger

%posttrans
if [ -e %_sbindir/weak-modules ]; then
Expand All @@ -54,14 +64,37 @@ if [ -e %_sbindir/weak-modules ]; then
fi
%systemd_postun_with_restart lkrg.service

%pre logger
# Ignore errors so that we don't fail if the user already exists
/usr/sbin/useradd -r lkrg-logger -d / -s /sbin/nologin || :
# Don't remove this user on package uninstall because the user may still own
# files under /var/log/lkrg-logger, which won't be removed if non-empty

%files
%defattr(-,root,root)
%doc CHANGES CONCEPTS LICENSE PATREONS PERFORMANCE README
%module_dir/*
%_unitdir/*
%_sysconfdir/sysctl.d/*
%_unitdir/lkrg.service
%config(noreplace) %_sysconfdir/sysctl.d/*

%files logger
%defattr(-,root,root)
%doc LOGGING
/usr/sbin/*
%_unitdir/lkrg-logger.service
%dir %attr(0750,lkrg-logger,lkrg-logger) /var/log/lkrg-logger

%changelog
* Tue Feb 27 2024 Solar Designer <[email protected]> 0.9.8-1
- Update to 0.9.8
- Add logger sub-package
- Mark the sysctl configuration file config(noreplace)
- Use "sort -V" to build against the latest installed version of kernel-devel

* Wed Nov 8 2023 Solar Designer <[email protected]> 0.9.7-4
- Add a couple of upstream patches, most notably to fix kINT false positives on
EL 8.8.

* Tue Oct 24 2023 Solar Designer <[email protected]> 0.9.7-3
- Use weak-modules if available so that on RHEL and its rebuilds the same LKRG
package build works across different kABI-compatible kernel revisions/builds
Expand Down
48 changes: 48 additions & 0 deletions logger/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
CC = gcc
LD = $(CC)
RM = rm -f
MKDIR = mkdir -p
INSTALL = install -c
CFLAGS = -Wall -W -O2 -fomit-frame-pointer
LDFLAGS = -s

DESTDIR =
PREFIX = /usr/local
SBINDIR = $(PREFIX)/sbin
UNITDIR = /etc/systemd/system

PROJ = lkrg-logger lkrg-logctl lkrg-keygen
LOGGER_OBJS = logger.o misc.o session.o
LOGCTL_OBJS = logctl.o
KEYGEN_OBJS = keygen.o
OBJS = $(LOGGER_OBJS) $(LOGCTL_OBJS) $(KEYGEN_OBJS)

all: $(PROJ)

lkrg-logger: $(LOGGER_OBJS)
$(LD) $(LDFLAGS) $(LOGGER_OBJS) -o $@

lkrg-logctl: $(LOGCTL_OBJS)
$(LD) $(LDFLAGS) $(LOGCTL_OBJS) -o $@

lkrg-keygen: $(KEYGEN_OBJS)
$(LD) $(LDFLAGS) $(KEYGEN_OBJS) -o $@

.c.o:
$(CC) $(CFLAGS) -c $*.c

install: $(PROJ)
$(MKDIR) -m 755 $(DESTDIR)$(SBINDIR)
$(INSTALL) -m 700 lkrg-logger $(DESTDIR)$(SBINDIR)/
$(INSTALL) -m 700 lkrg-logctl $(DESTDIR)$(SBINDIR)/
$(INSTALL) -m 755 lkrg-keygen $(DESTDIR)$(SBINDIR)/
if [ -d $(DESTDIR)$(UNITDIR) ]; then \
umask 022; \
sed "s,/usr,$(PREFIX)," lkrg-logger.service > $(DESTDIR)$(UNITDIR)/lkrg-logger.service; \
fi

uninstall:
$(RM) $(DESTDIR)$(SBINDIR)/lkrg-{logger,logctl,keygen} $(DESTDIR)$(UNITDIR)/lkrg-logger.service

clean:
$(RM) $(PROJ) $(OBJS)
1 change: 1 addition & 0 deletions logger/hydrogen
23 changes: 23 additions & 0 deletions logger/keygen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Generate a public/secret keypair.
*
* Written in 2022 by Solar Designer
* Copyright (c) 2022 Binarly
*/

#include <stdio.h>

#include "hydrogen/hydrogen.c"

int main(void)
{
hydro_kx_keypair server_static_kp;
char hex[(hydro_kx_PUBLICKEYBYTES | hydro_kx_SECRETKEYBYTES) * 2 + 1];

hydro_kx_keygen(&server_static_kp);

printf("LKRG_LOGGER_PK=%s\n", hydro_bin2hex(hex, sizeof(hex), server_static_kp.pk, hydro_kx_PUBLICKEYBYTES));
printf("LKRG_LOGGER_SK=%s\n", hydro_bin2hex(hex, sizeof(hex), server_static_kp.sk, hydro_kx_SECRETKEYBYTES));

return 0;
}
16 changes: 16 additions & 0 deletions logger/lkrg-logger.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=Linux Kernel Runtime Guard remote logging server
Documentation=https://lkrg.org
After=network.target

[Service]
Type=simple
EnvironmentFile=/etc/lkrg-logger.conf
ExecStart=/usr/sbin/lkrg-logger -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target
Loading
Loading