Wie eine scheinbar fehlerhafte USB-C-Firmware journald abschießt

„Ein Problem mit einer Systemanwendung wurde festgestellt.“ Bei jedem Aufwachen aus dem Standby.

Die Spur

In /var/crash/ lagen drei Berichte. Der spannende: systemd-journald, Signal 6 (SIGABRT). Und das siginfo verrät den Täter: si_pid = 1. Den Abbruch hat systemd selbst geschickt. Ein Watchdog-Kill:

systemd-journald.service: Watchdog timeout (limit 3min)!
Killing process 119999 (systemd-journal) with signal SIGABRT.

journald hängt drei Minuten, also schießt PID 1 es ab. Dreizehnmal in einer Woche. Warum hängt es? Weil es nicht hinterherkommt:

Missed 221232 kernel messages
/dev/kmsg buffer overrun, some messages lost.

Irgendwer flutet den Kernel-Log. Der Schuldige, 332.584-mal in einem Boot, drei pro Sekunde, ununterbrochen:

ucsi_acpi USBC000:00: bogus connector number in CCI: 2

Der falsche Verdächtige

Naheliegend: Am USB-C Port hängt nur ein älteres Netzteil von einem Dell Laptop.
Markenfremdes USB-C Power Delivery, das klingt nach Verhandlung, die schiefgeht. Ein perfekter Verdächtiger.

Also systematisch testen:

  • Netzteil abgezogen → Sturm läuft unverändert, 3,6/s.
  • Modul neu geladen, Port leer → Sturm startet von selbst.
  • Kalt gebootet, nichts eingesteckt → Sturm da, plus UCSI_GET_PDOS failed (-70).
  • Anker 737, 140 W, USB-C Powerbank → kein typec-Partner, alles null, Sturm identisch.

Jede Variable einzeln eliminiert. Der Lader ist unschuldig, jeder Lader ist unschuldig.

Die eigentliche Ursache

Die UCSI-Firmware des Acer Aspire A14-52M ist scheinbar fehlerhaft. Der Embedded Controller beantwortet UCSI-Kommandos mit Kommunikationsfehler. Der Kernel-Treiber ucsi_acpi merkt das, verwirft es und fragt sofort wieder. Endlosschleife. Geladen wird trotzdem: Der EC handelt die Leistung in Hardware aus, völlig unabhängig OS. Deshalb fiel mir nie ein Ladeproblem auf.

Und die SSD?

Der Reflex: So ein Log-Sturm zerschreibt doch die NVMe. Nachgerechnet: rund 21 Millionen identische Zeilen pro Jahr, von journald gnadenlos dedupliziert auf ein paar hundert Byte pro Eintrag: fünf bis acht Gigabyte im Jahr. Bei einer 2-TB-TLC mit ~1.200 TBW sind das 0,0005 % der Lebensdauer pro Jahr. SMART sagt nach 6,14 TB nüchtern: Percentage Used: 0%. Die SSD hat es nicht mal bemerkt.

Der Fix

Acer hat (Stand BIOS V1.32, November 2025) nichts gepatcht, fwupd kennt kein Update. Und der UCSI-Stack tut auf dieser Maschine scheinbar eh nichts Nützliches (die Hardware handelt PD auch ohne das OS, incl. unterschiedlicher Ladeleistung, je nach Netzteil). Also raus damit:

echo "blacklist ucsi_acpi"     | sudo tee /etc/modprobe.d/blacklist-ucsi_acpi.conf
echo "install ucsi_acpi /bin/true" | sudo tee -a /etc/modprobe.d/blacklist-ucsi_acpi.conf
sudo update-initramfs -u

Laden, USB-C-Daten, Thunderbolt, DisplayPort — alles läuft weiter über EC und Retimer. Verloren geht nur die USB-C-Telemetrie, die hat aber sowieso sowieso nur Nullen geliefert. Sturm vorbei, Log wieder übersichtlich.

Lehre: Der naheliegende Verdächtige, das fremde Netzteil, war eine saubere Sackgasse. Erst der leere Port im Kaltstart hat die Firmware überführt. Messen schlägt Raten.


One more thing — für die, die’s genau wissen wollen

Ab hier wird’s schmutzig: Coredump auspacken und im Debugger nachsehen, woran journald genau hängengeblieben ist. Wen nur der Fix interessiert, ist oben fertig. Wer wissen will, wie man so eine Aussage wie „PID 1 hat es abgeschossen“ belegt, liest weiter.

Die .crash-Datei ist ein apport-Bericht mit base64-verpacktem Coredump. Auspacken:

apport-unpack /var/crash/_usr_lib_systemd_systemd-journald.0.crash /tmp/jd

Symbole hat man lokal keine, also Ubuntus debuginfod ziehen lassen und den Stack der abgestürzten Thread ansehen:

DEBUGINFOD_URLS=https://debuginfod.ubuntu.com \
  gdb -batch -ex 'set debuginfod enabled on' \
      -ex 'file /usr/lib/systemd/systemd-journald' \
      -ex 'core-file /tmp/jd/CoreDump' \
      -ex 'bt' -ex 'print $_siginfo'

Und da steht alles drin:

Program terminated with signal SIGABRT, Aborted.
#0  __GI___libc_read (fd=146, buf=..., nbytes=4104) at read.c:26
#1  read_virtual_file_fd () from libsystemd-shared-255.so
#2  read_virtual_file_at () from libsystemd-shared-255.so
#3  device_read_uevent_file () from libsystemd-shared-255.so
#4  sd_device_get_devname () from libsystemd-shared-255.so
#5  ...
#6  sd_event_dispatch ()
#7  sd_event_run ()

Der Thread klemmt in einem read() auf Dateideskriptor 146 — einer sysfs-uevent-Datei, gelesen über sd_device_get_devname(). journald wollte zu einem hereinflatternden Geräte-Event den Namen auflösen und blieb im virtuellen Dateisystem hängen. Drei Minuten lang. Genau die Sorte Stall, die der Watchdog bestraft.

Und der Beweis, dass es ein Watchdog-Kill war und kein interner abort(), steht im siginfo:

$1 = {si_signo = 6, si_code = 0,
      _sigchld = {si_pid = 1, si_uid = 0}}

si_code = 0 ist SI_USER, das Signal kam von einem kill(), nicht aus dem Prozess selbst. Und si_pid = 1: Absender ist PID 1, systemd.