Lese-Ansicht

E-Mails mit Python lesen: imaplib

Für die Neuauflage meines Scripting-Buchs habe ich mich zuletzt mit dem Senden und Empfangen von E-Mails per SMTP und IMAP beschäftigt. Dieser Blog-Beitrag stellt das Standardmodul imaplib vor. Damit können Sie per IMAP Postfächer abrufen und verwalten. Die Anwendung ist ein wenig umständlich, aber dafür können Sie wirklich praktisch alles machen, was das Protokoll IMAP vorsieht.

Kurz erklärt: IMAP und Authentifizierung

IMAP (Internet Message Access Protocol) ist das Standardprotokoll zum Abrufen und Verwalten von E-Mails auf einem Mailserver. Die Verbindung erfolgt normalerweise über Port 993 mit SSL/TLS. Im Unterschied zu POP3 verbleiben die Nachrichten auf dem Server und lassen sich in Ordnern organisieren – IMAP eignet sich daher besonders gut für die automatisierte Verarbeitung.

Klassische Unix/Linux-Mailserver erlauben die Anmeldung mit Benutzername und Passwort. Bei Google-Konten ist das anders: Gmail erfordert entweder App-Passwörter (16-stellige Codes, die Sie nach Aktivierung der Zwei-Faktor-Authentifizierung unter myaccount.google.com/apppasswords erstellen) oder OAuth2. App-Passwörter sind dabei die einfachere Variante für Scripts.

Zugangsdaten sicher verwalten

Passwörter sollten nie direkt im Scriptcode stehen. Die Beispiele hier lesen die Zugangsdaten aus Umgebungsvariablen, die wiederum aus einer Datei credentials.env geladen werden:

# credentials.env  (chmod 600; in .gitignore aufnehmen!)
IMAP_HOST=mail.example.com
IMAP_USER=username
IMAP_PASS=topSecret

In Python laden Sie die Datei am einfachsten mit python-dotenv:

from dotenv import load_dotenv
load_dotenv("credentials.env")

Das Modul installieren Sie mit pip install python-dotenv oder – wenn Sie uv verwenden – mit uv add python-dotenv.

imaplib: Verbinden, suchen und herunterladen

imaplib ist seit Python 2 Bestandteil der Standardbibliothek und deckt den vollständigen IMAP-Befehlssatz ab. Das folgende Beispiel-Script stellt die Verbindung zur Inbox her, lädt die zehn neuesten E-Mails herunter und zeigt die wichtigsten Metadaten tabellarisch an – mit * als Indikator für noch ungelesene Nachrichten:

* 13-05 17:53  papa.xxx@xxx...     AW: Halbjahresabrechnungen
  12-05 20:48  kundenxxx@xxx...    Terminanfrage Sendungszustel...
  12-05 04:02  info@weltxxx...     Japan, Korsika oder Sansibar ...
  11-05 20:51  noreply@xxx...      OpenAI Dev News: Realtime 2.0...
  05-05 18:58  cron@webxxx         Invitation updated: iprot dev 
  04-05 08:28  externexxx@fhxxx... Vertrag bereit zur Abbrechnung

imaplib.IMAP4_SSL stellt die Verbindung zum IMAP-Server auf Port 993 her. select öffnet einen Ordner, search liefert eine Liste von Nachrichten-IDs als leerzeichen-getrennte Byte-Zeichenkette, fetch lädt die Rohdaten einer einzelnen oder mehrerer Nachrichten.

Der Parameter readonly=True bei select stellt sicher, dass das Abrufen der Nachrichten keine Nebeneffekte hat – insbesondere werden keine Nachrichten als gelesen markiert. Das ist wichtig, weil IMAP-Server den Status einer Nachricht bereits beim Öffnen verändern können.

search(None, "ALL") liefert eine aufsteigend sortierte Liste aller Nachrichten-IDs im Postfach. Mit split()[-10:] extrahieren Sie die zehn neuesten. Diese IDs werden, getrennt durch Kommas, zu einem einzigen fetch-Aufruf zusammengefasst. Als Fetch-Attribute übergeben Sie FLAGS für den Lesestatus sowie BODY.PEEK[HEADER.FIELDS (...)], um nur die benötigten Header-Felder abzurufen. PEEK verhindert dabei, dass der Server die Nachrichten automatisch als gelesen kennzeichnet.

Jede Zeile der Server-Antwort ist ein Tupel aus Metadaten und rohen Header-Bytes. ParseFlags wertet die Metadaten aus und gibt die IMAP-Flags als Tupel zurück. Wenn \Seen fehlt, gilt die Nachricht als ungelesen. message_from_bytes wandelt die Header-Bytes in ein auswertbares Objekt um.

parsedate_to_datetime macht aus einem RFC-2822-Datum ein datetime-Objekt, das dann mit strftime nach eigenen Vorstellungen formatiert werden kann. parseaddr zerlegt das From-Feld in ein (Name, Adresse)-Tupel. MIME-kodierte Header-Zeichenketten wie =?utf-8?q?...?= entschlüsselt decode_header aus dem Modul email.header.

Die Ergebnisse werden zunächst in einer Liste gesammelt, da die Reihenfolge der Server-Antwort nicht zwingend der Reihenfolge der angefragten IDs entspricht. reversed dreht die Liste beim Ausgeben um, sodass die neueste Nachricht zuerst erscheint.

# Beispieldatei fetch-imap.py
import os, email, imaplib
from email.header import decode_header, make_header
from email.utils import parsedate_to_datetime, parseaddr
from dotenv import load_dotenv

# IMAP-Konfigurationsparameter lesen
load_dotenv("credentials.env")
HOST = os.environ["IMAP_HOST"]
USER = os.environ["IMAP_USER"]
PASS = os.environ["IMAP_PASS"]

# RFC-2047-Header (=?utf-8?q?...?=) dekodieren
def decode_mime(value: str | None) -> str:
    return str(make_header(decode_header(value or "")))

# Zeichenkette auf max_len verkürzen
def truncate(text: str, n: int) -> str:
    return text if len(text) <= n else text[: n - 3] + "..."

# Verbindung zum IMAP-Server
with imaplib.IMAP4_SSL(HOST) as imap:
    imap.login(USER, PASS)
    imap.select("INBOX", readonly=True)  # nichts ändern!

    # IDs aller Nachrichten ermitteln -> Byte-String für fetch()
    _, data = imap.search(None, "ALL")
    id_set = b",".join(data[0].split()[-10:])  # max. 10

    # IDs der ungelesenen Nachrichten
    _, unseen_data = imap.search(None, "UNSEEN")
    unseen = set(unseen_data[0].split())

    # relevante Spalten abfragen (IMAP-Syntax); PEEK, damit
    # das Seen-Flag nicht gesetzt wird
    fields = "(FLAGS BODY.PEEK[HEADER.FIELDS (DATE FROM SUBJECT)])"
    _, rows = imap.fetch(id_set, fields)

    # Daten/Spalten dekodieren und formatieren
    messages = []
    for row in rows:
        if not isinstance(row, tuple):
            continue
        meta, raw_headers = row
        # Sequence-Nummer am Beginn der Metadaten (b'4 (FLAGS ...')
        seq     = meta.split()[0]
        is_new  = seq in unseen
        msg     = email.message_from_bytes(raw_headers)
        dt      = parsedate_to_datetime(msg["Date"])
        date    = dt.strftime("%d-%m %H:%M")
        addr    = parseaddr(decode_mime(msg.get("From", "")))[1]
        sender  = truncate(addr, 20)
        raw_sub = decode_mime(msg.get("Subject", "(no subject)"))
        subject = truncate(raw_sub, 40)
        messages.append((is_new, date, sender, subject))

    # in umgekehrter Reihenfolge ausgeben, die neueste Mail zuerst
    for is_new, date, sender, subject in reversed(messages):
        flag = "*" if is_new else " "
        print(f"{flag} {date}  {sender:<20}  {subject}")

Was imaplib sonst noch kann

Das obige Beispiel kratzt nur an der Oberfläche. imaplib deckt den vollständigen IMAP-Befehlssatz ab:

  • Vollständige Nachrichten laden: Mit fetch können Sie nicht nur Header, sondern auch den kompletten Nachrichtentext inklusive Anhänge abrufen.
  • Filtern: search akzeptiert IMAP-Suchkriterien wie FROM, SUBJECT, SINCE oder UNSEEN, um gezielt nach bestimmten Nachrichten zu suchen.
  • Flags setzen: store setzt oder entfernt Flags wie \Seen, \Flagged oder \Deleted.
  • Löschen: expunge löscht die als \Deleted markierten Nachrichten endgültig.
  • Ordner verwalten: copy verschiebt Nachrichten zwischen Ordnern, list gibt alle verfügbaren Mailboxen zurück, create und delete legen neue Ordner an oder entfernen sie.

Kurz gesagt: Von der einfachen Posteingangsübersicht bis zur vollautomatisierten Mailbox-Verwaltung ist alles drin.

Alternativen zu imaplib

Wer die etwas sperrige API von imaplib als mühsam empfindet, kann auf IMAPClient ausweichen. Die Bibliothek ist ein High-Level-Wrapper um imaplib, der insbesondere den Umgang mit Nachrichten-IDs, Flags und Ordnern deutlich angenehmer macht. Das folgende Mini-Beispiel zeigt die Verbindung und das Abrufen der Betreffzeilen aller ungelesenen Nachrichten:

from imapclient import IMAPClient

with IMAPClient(HOST) as client:
    client.login(USER, PASS)
    client.select_folder("INBOX", readonly=True)
    messages = client.search("UNSEEN")
    for uid, data in client.fetch(messages, "ENVELOPE").items():
        print(data[b"ENVELOPE"].subject.decode())

IMAPClient installieren Sie mit pip install imapclient bzw. uv add imapclient.

Wer IMAP in einem asyncio-Kontext benötigt, greift zu aioimaplib – einer vollständig async-fähigen Bibliothek, da imaplib synchron blockiert. Und imbox ist eine sehr einsteigerfreundliche Abstraktion, die E-Mails als Python-Objekte mit direkt zugänglichen Attributen wie .subject oder .attachments liefert. Der Nachteil: weniger Kontrolle bei komplexen Operationen.

Quellen und Links

  •  

Urlaub mit dem Lama

Urlaub ist herrlich, um einfach mal abzuschalten. Doch nach ein paar Tagen der puren Erholung packt mich meistens wieder der Drang, etwas Kreatives oder Produktives zu tun. Ein gutes Buch lesen? Schon erledigt. Rätseln? Nun ja, dieses Jahr hatte ich mir Sudoku als Endgegner ausgesucht – was mich am Ende ehrlicherweise mehr angestrengt als erfreut hat. Immerhin war ich an anderer Stelle produktiv und habe die Auffrischung meines A2-Fernpiloten-Kompetenznachweises erfolgreich hinter mich gebracht.

Doch der Tech-Spleen lässt einen auch im Urlaub nicht ganz los. Mir ging da nämlich eine Sache durch den Kopf: Letztes Jahr hat Prof. Klaus Knopper auf den Chemnitzer Linux-Tagen einen extrem spannenden Vortrag zum Thema lokale KI gehalten. Konkret ging es um Ollama auf dem Raspberry Pi. Warum also nicht die freie Zeit nutzen, um das Ganze mal aus der Ferne auf dem heimischen RasPi zu installieren und selbst auszuprobieren?

Was ist Ollama?

Für alle, die den Begriff noch nicht gehört haben, hilft ein kurzer Blick in die Wikipedia:

Ollama ist eine Open-Source-Software zur lokalen Ausführung von Large Language Models (LLMs) auf Desktop-Computern. Die Plattform ermöglicht die lokale Nutzung frei verfügbarer KI-Modelle und unterstützt die Integration mit weiteren lokalen Werkzeugen, die über eine Kommandozeilenschnittstelle oder eine Programmierschnittstelle (API) angebunden werden können. Ollama ist für macOS, Linux und Windows verfügbar.

Installation

Gesagt, getan. Die Installation auf dem Raspberry Pi – in meinem Fall ein Raspberry Pi 5 mit 8 GB RAM – erfolgt denkbar einfach über das Terminal mit folgendem Befehl:

curl -fsSL https://ollama.com/install.sh | sh

Am Ende des Installationsvorgangs spuckt das System noch den dezenten Hinweis aus, dass keine NPUs oder Grafikkarten von Nvidia gefunden wurden, die die Ausführung des Large Language Models beschleunigen könnten. Das war beim RasPi natürlich zu erwarten, hält uns aber nicht auf.

Damit wir der KI überhaupt Fragen stellen können, muss im Anschluss ein passendes und vor allem schlankes Modell installiert werden. Für diesen ersten Test habe ich mich für llama 3.2 (ca. 2 GB) entschieden:

ollama run llama3.2:3b

Der Praxistest: Was taugt die lokale KI?

Nachdem das Modell geladen war, wollte ich es natürlich wissen. Ich habe der lokalen KI eine klassische Frage gestellt:

Welche Linux-Distribution würdest du einem Anfänger empfehlen?

Eine gute Frage!

Als Anfänger ist es wichtig, eine Linux-Distribution zu wählen, die leicht zu installieren und zu bedienen ist. Hier sind einige beliebte Optionen:

  1. Ubuntu: Ubuntu ist eine der bekanntesten und am weitesten verbreiteten Linux-Distributionen. Sie bietet eine intuitive Benutzeroberfläche und eine riesige Gemeinschaft von Benutzern, die ihr helfen können, wenn
    etwas nicht funktioniert.
  2. Linux Mint: Linux Mint basiert auf Ubuntu und ist für ihre einfache und benutzerfreundliche Oberfläche bekannt. Sie ist auch sehr sicher und bietet viele zusätzliche Funktionen wie eine verbesserte
    Sicherheitsfunktion und eine integrierte Diskografie.
  3. Debian: Debian ist eine weitere beliebte Linux-Distribution, die für ihre Stabilität und Sicherheit bekannt ist. Sie bietet eine riesige Auswahl an Software und ist ein beliebter Kandidat für Entwickler und
    Systemadministratoren.
  4. Fedora: Fedora ist eine Linux-Distribution, die von der Open Source Initiative verwaltet wird. Sie bietet eine aktuelle und sichere Version von Linux und ist ein beliebter Kandidat für Entwickler und
    Systemadministratoren.

Meine Empfehlung wäre Ubuntu. Sie ist eine großartige Option für Anfänger, da sie leicht zu installieren und zu bedienen ist. Außerdem bietet sie eine riesige Gemeinschaft von Benutzern, die ihr helfen können, wenn
etwas nicht funktioniert.

Ich hoffe, das hilft! Wenn du noch weitere Fragen hast, stehe ich gerne zur Verfügung.

Das Ergebnis kann sich absolut sehen lassen. Die Antwort hätte ich so oder so ähnlich wahrscheinlich auch gegeben. Ich bin wirklich nachhaltig beeindruckt, was der kleine Einplatinen-Computer hier ganz ohne Cloud-Anbindung zu leisten vermag.

Fazit

Eine lokale und ethische KI auf dem eigenen Raspberry Pi ist auf jeden Fall einen Blick wert. Wer seine Daten nicht ungeschützt den großen Hyperscalern in die Cloud blasen möchte, findet hier eine fantastische Alternative. Im Sinne der digitalen Souveränität ist diese Lösung für kleinere, alltägliche Aufgaben auf jeden Fall hervorragend geeignet.

Der Beitrag Urlaub mit dem Lama erschien zuerst auf intux.de.

  •  

Kernel Live Patching für Red Hat Enterprise Linux (RHEL)

Dieser Artikel richtet sich an jene, die sich für das Thema Kernel Live Patching (KLP) interessieren.

Im ersten Teil des Artikels stelle ich dar, wann KLP in meinen Augen keine gute Lösung darstellt und man auf den Einsatz nach Möglichkeit verzichten sollte. Wissend, dass es manchmal nicht anders geht, beschreibe ich im zweiten Teil am Beispiel von RHEL 9, wie KLP eingerichtet und genutzt werden kann.

Transparenzhinweis: Ich arbeite als Technical Account Manager (TAM) für die Firma Red Hat, welche die Distribution Red Hat Enterprise Linux (RHEL) herausgibt. Dieser Artikel spiegelt meine persönliche Meinung wider, welche mit der meines Arbeitgebers übereinstimmen kann, dies jedoch nicht in jedem Fall muss.

Der Userspace wird in diesem Artikel ausgeklammert, um den Umfang nicht zu sprengen. Ich werde diesen in einem folgenden Artikel aufgreifen.

Warum bzw. wann man Kernel Live Patching nicht nutzen sollte

Folgende Gründe sollten nicht zur Nutzung von KLP führen, sondern auf andere Weise adressiert werden:

  • Angst vor dem Serverneustart
  • Eine Softwarearchitektur, die Serverneustarts nicht vorsieht/zulässt
  • Ungeklärte Abhängigkeiten in vernetzten Systemen
  • Der Glaube, mit KLP nie wieder neustarten zu müssen

Angst ist in der IT ein ganz schlechter Ratgeber. Hier sollte unbedingt die Ursache und nicht das Symptom behandelt werden. Denn Serverneustarts können auch noch aus folgenden Gründen passieren bzw. notwendig werden:

  • Der Server verliert vorübergehend die Stromversorgung
  • Eine Kernel Panic bringt das System zum Absturz
  • Ein nicht mehr reagierendes System muss durch einen Reset neugestartet werden
  • Umzug der Hardware an einen neuen Standort

Dies sind nur vier Gründe, die mir sofort in den Sinn kommen. Wenn wir länger darüber nachdenken, fallen uns bestimmt noch viele weitere ein (ergänzt diese gern in den Kommentaren). Wichtig ist zu verstehen, dass Serverneustarts aus verschiedenen Gründen passieren und per se nicht schlimm sind.

Wenn die Softwarearchitektur keine Neustarts einzelner Komponenten zulässt, hat man ein ganz anderes Problem, welches dringend adressiert werden sollte. Soetwas wie 100%-tige Verfügbarkeit gibt es nicht. Hier ist in meinen Augen zu klären, ob es wirklich an der Anwendung oder eher an nicht verhandelten Wartungsfenstern liegt. KLP ist hier keine Lösung, da die Häufigkeit von Neustarts nur reduziert bzw. das Problem in die Zukunft verschoben wird.

Viele Sysadmins sind faul und das ist gut so. Motiviert es diese Personengruppe doch, manuelle Tätigkeiten zu automatisieren und sich die Arbeit zu erleichtern. Diese Faulheit darf allerdings nicht dazu führen, dass man sich vor der Analyse komplexer und vernetzter Systeme drückt. Abhängigkeiten können analysiert und in den meisten Fällen aufgelöst werden. Sind sie bekannt, kann man sie im Patchprozess berücksichtigen und den Vorgang inkl. Neustarts automatisieren. Auch in diesem Fall verzögert KLP das Unvermeidliche nur.

Kernel Live Patching kümmert sich, wie der Name schon sagt, nur um den Kernel. Was ist mit dem Userspace? Auch hier gibt es sicherheitskritische Bibliotheken und Anwendungen, wie z.B. openssl, gnutls oder die glibc, welche bei erkannten Schwachstellen zeitnah abgesichert werden müssen, um die Sicherheit des Systems nicht zu gefährden.

Neustarts sind per se nicht schlecht. Wer seine Server regelmäßig neustartet, gewinnt Vertrauen, dass diese auch wieder hochfahren und ihre Dienste korrekt erbringen. Schlummernde Probleme werden schneller erkannt und türmen sich nicht zu einem Störfall auf, der nur darauf wartet, im ungünstigsten Moment zu passieren. Und im Optimalfall sind die Dienste so entworfen worden, dass der Ausfall/Neustart eines einzelnen Servers nicht automatisch zu einer Nichtverfügbarkeit des Dienstes führt.

Ich möchte mein Plädoyer für Serverneustarts an dieser Stelle beenden und mich zwei Szenarios zuwenden, in denen KLP die Schmerzen des IT-Betriebs lindern kann.

Wann Kernel Live Patching Sinn macht

Für besonders geschäftskritische IT-Dienste existieren häufig Service-Level-Agreements (SLA), die eine sehr hohe Verfügbarkeit garantieren. Verstöße gegen diese SLA werden von den Stakeholdern meist nicht toleriert und sind in manchen Fällen mit Vertragsstrafen belegt. Zwar gilt auch hier, dass das Problem eher in der Softwarearchitektur liegt, doch hilft dies den Sysadmins nicht, die mit dem Betrieb beauftragt sind. Sie müssen irgendwie damit umgehen, bis eine bessere Lösung gefunden wird. Hier kann KLP eine Notlösung sein, um Sicherheitsrisiken im Betrieb zu reduzieren und SLA-Verstöße zu vermeiden.

Angelehnt an die SLA spielt die Zeit, die ein Server für einen Neustart benötigt, eine Rolle. Während die meisten VMs in Sekunden oder 1-2 Minuten neustarten, dauert dieser Vorgang bei Hardwareservern manchmal deutlich länger. Im Feld werden hier vereinzelt Zeiten zwischen 10-20 Minuten beobachtet (pro Server). Müssen mehrere Server für einen IT-Dienst sequentiell neugestartet werden, summieren sich die Zeiten schnell auf und machen größere Wartungsfenster erforderlich. KLP kann helfen, die Anzahl der langen Wartungsfenster zu reduzieren.

Es gibt Systeme, für deren Start ein manueller Eingriff durch Sysadmins notwendig ist. Dies kann z.B. die Eingabe eines BIOS-, Grub-, LUKS- oder UEFI-Passworts sein. Dies ist aufwändig und lästig, lässt sich aber leider nicht in allen Fällen wegautomatisieren. Auch hier erscheint es legitim, die Anzahl der manuellen Eingriffe durch den Einsatz von KLP zu minimieren.

Kernel Live Patching für RHEL 9 konfigurieren

Um mich für die Konfiguration vorzubereiten, habe ich folgende drei Quellen studiert:

Die wichtigsten Erkenntnisse daraus sind für mich:

  • Nicht jeder RHEL-Kernel erhält Live-Patches
  • An jedem 1. März, Juni, September und Dezember (jedes Quartal) wird für jedes unterstützte RHEL-Release ein Kernel festgelegt, welcher Live-Patches erhält
  • Für jeden dieser Kernel verspricht Red Hat bis zu einem Jahr lang Updates für CVEs, die nach Red Hats Ermessen als critical oder important kategorisiert wurden (siehe Severity Ratings)

Dass Red Hat für ausgewählte Kernel-Releases ein Jahr lang Live-Patches bereitstellt, lässt nicht den Schluss zu, nur noch einmal pro Jahr neustarten zu müssen. Denn:

  • CVEs der Kategorien moderate und low werden gar nicht adressiert
  • Man erhält keinerlei Bugfixes und keinerlei Produktverbesserungen (Red Hat Enhancement Advisories (RHEA))

Die Planung eines Neustarts wird jedoch ggf. vereinfacht.

Konfiguration von Kernel Live Patching für ein Labor-System

Ich habe ein Labor-System mit RHEL 9 auserkoren, welches als Hypervisor für einige Libvirt/KVM-VMs genutzt wird.

Dieses läuft aktuell mit dem Kernel 5.14.0-687.15.1.el9_8.x86_64, welcher laut Kernel Live Patch life cycles kein Kernel ist, für den KLP angeboten wird. Es ist also zuerst der kernel-5.14.0-687.10.1 zu installieren. Anschließend folge ich der Dokumentation, um den Live-Patch-Stream für diesen Kernel zu aktivieren (siehe folgender Codeblock).

~]$ sudo dnf search kernel-5.14.0-687.10.1.el9_8
Updating Subscription Management repositories.
Last metadata expiration check: 0:04:34 ago on Tue 23 Jun 2026 11:31:09 AM CEST.
================ Summary Matched: kernel-5.14.0-687.10.1.el9_8 ================
kpatch-patch-5_14_0-687_10_1.x86_64 : Initial empty kpatch-patch for
                                    : kernel-5.14.0-687.10.1.el9_8.x86_64
~]$ sudo dnf install kpatch-patch-5_14_0-687_10_1.x86_64

Wie im obigen Codeblock zu sehen, handelt es sich dabei um den initialen und leeren kpatch-patch. Das System hat also noch keinen Fix erhalten, sondern ist lediglich darauf vorbereitet.

Im jetzigen Zustand würde DNF das System bei einem Update jedoch auf die letzte verfügbare Kernelversion aktualisieren, welche keine Live-Patches erhält. Da dies von mir nicht gewünscht ist, aktiviere ich einen Filter, der zukünftig nur noch KLP-fähige Kernel anzeigt. Der folgende Codeblock zeigt den Zustand vor der Aktivierung des Filters, die Aktivierung selbst und den Zustand danach.

~]$ sudo dnf kpatch status
Updating Subscription Management repositories.
Last metadata expiration check: 0:04:36 ago on Tue 23 Jun 2026 11:43:44 AM CEST.
Kpatch update setting: auto-update
Kpatch filter setting: no-filter
Dependencies resolved.
Nothing to do.
Complete!

~]$ sudo dnf kpatch auto-filter
Updating Subscription Management repositories.
Kpatch filter setting: auto-filter

~]$ sudo dnf kpatch status
Please note, kpatch filter is enabled, only kpatch supported kernels are shown.
Kpatch update setting: auto-update
Kpatch filter setting: auto-filter
Dependencies resolved.
Nothing to do.
Complete!

Zum Abschluss ein Neustart und mein System läuft mit dem richtigen Kernel 5.14.0-687.10.1.el9_8.x86_64.

Aufräumarbeiten

Aktuell sind auf meinem System noch Kernel-Pakete installiert, die für KLP nicht vorgesehen sind, aber bei einem dnf update aktualisiert werden würden:

~]# dnf list --installed kernel*
Updating Subscription Management repositories.
Please note, kpatch filter is enabled, only kpatch supported kernels are shown.
Installed Packages
kernel.x86_64              5.14.0-611.55.1.el9_7 @rhel-9-for-x86_64-baseos-rpms
kernel.x86_64              5.14.0-687.10.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel.x86_64              5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-core.x86_64         5.14.0-611.55.1.el9_7 @rhel-9-for-x86_64-baseos-rpms
kernel-core.x86_64         5.14.0-687.10.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-core.x86_64         5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-devel.x86_64        5.14.0-611.38.1.el9_7 @rhel-9-for-x86_64-appstream-rpms
kernel-devel.x86_64        5.14.0-611.55.1.el9_7 @rhel-9-for-x86_64-appstream-rpms
kernel-devel.x86_64        5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-appstream-rpms
kernel-headers.x86_64      5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-appstream-rpms
kernel-modules.x86_64      5.14.0-611.55.1.el9_7 @rhel-9-for-x86_64-baseos-rpms
kernel-modules.x86_64      5.14.0-687.10.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-modules.x86_64      5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-modules-core.x86_64 5.14.0-611.55.1.el9_7 @rhel-9-for-x86_64-baseos-rpms
kernel-modules-core.x86_64 5.14.0-687.10.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-modules-core.x86_64 5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-tools.x86_64        5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms
kernel-tools-libs.x86_64   5.14.0-687.15.1.el9_8 @rhel-9-for-x86_64-baseos-rpms

Um aufzuräumen, habe ich alle überflüssigen Pakte entfernt, bis nur noch der KLP-fähige Kernel vorhanden ist:

~]# dnf list --installed kernel*
Updating Subscription Management repositories.
Please note, kpatch filter is enabled, only kpatch supported kernels are shown.
Installed Packages
kernel.x86_64                5.14.0-687.10.1.el9_8   @rhel-9-for-x86_64-baseos-rpms
kernel-core.x86_64           5.14.0-687.10.1.el9_8   @rhel-9-for-x86_64-baseos-rpms
kernel-modules.x86_64        5.14.0-687.10.1.el9_8   @rhel-9-for-x86_64-baseos-rpms
kernel-modules-core.x86_64   5.14.0-687.10.1.el9_8   @rhel-9-for-x86_64-baseos-rpms

Verhalten bei zukünftigen Updates

Durch den konfigurierten kpatch-Filter werden bei zukünftigen Updates nur Kernel aufgeführt, die KLP-fähig sind. Wird ein KLP veröffentlicht, erscheint dieser als kpatch-patch in der Ausgabe von dnf up`. Der folgende (gekürzte) Codeblock zeigt dies beispielhaft.

~]# dnf up
Updating Subscription Management repositories.
Please note, kpatch filter is enabled, only kpatch supported kernels are shown.
Dependencies resolved.
===================================================================================
 Package       Arch   Version               Repository                        Size
===================================================================================
Upgrading:
…
kpatch-patch-5_14_0-687_10_1 x86_64 1-1.el9_8 rhel-9-for-x86_64-baseos-rpms   22 k
…

Mit dem Befehl aus dem nächsten Codeblock kann kontrolliert werden, welche KLP aktuell installiert sind und welche CVEs sie adressieren.

~]# kpatch list
Loaded patch modules:
kpatch_5_14_0_687_10_1_1_1 [enabled]
	CVE-2026-43037

Installed patch modules:
kpatch_5_14_0_687_10_1_1_1 (5.14.0-687.10.1.el9_8.x86_64)

Obige Ausgabe bestätigt, dass ein KLP aktiv ist, der die kritische Schwachstelle CVE-2026-43037 schließt.

Fazit

KLP funktioniert und ist einfach einzurichten. Es ist nicht in jedem Fall die richtige Lösung und löst nicht alle Probleme, kann jedoch in manchen Fällen die Schmerzen im IT-Betrieb lindern.

Der Userspace wurde ausgeklammert, um den Umfang dieses Artikels nicht zu sprengen. Dies hebe ich mir für einen folgenden Artikel auf.

  •  
❌