Softwareentwicklung
MongoDB 8 stirbt leise - wenn die CPU die Datenbank für einen Angreifer hält
Neckar IT · · Aktualisiert:

Kein Stack Trace. Kein dmesg-Eintrag. Nur ein Restart-Loop alle 29 Sekunden — weil MongoDB 8 auf Linux Kernel 7 mit AMD Zen 4/5 beim ersten Fiber-Switch den Stecker gezogen bekommt.
Update (Juni 2026)
Ab MongoDB 8.3.1 stirbt der Server nicht mehr leise.
Das in diesem Artikel beschriebene Verhalten — stiller SIGSEGV, Exit-Code 139, kein Log, Restart-Loop alle 29 Sekunden — gilt für die älteren MongoDB-8-Builds, mit denen wir das Problem ursprünglich diagnostiziert haben. Ab MongoDB 8.3.1 hat MongoDB den stillen Crash durch einen Fail-fast-Startup-Guard ersetzt: Der Server bricht jetzt sofort beim Start ab (Exit-Code 1) und schreibt eine klare Fehlermeldung ins Log:
F CONTROL MongoDB cannot start: Linux kernel versions 6.19 and newer has a
known incompatibility with this version of MongoDB. See
https://jira.mongodb.org/browse/SERVER-121912 for more information.
Der Workaround bleibt identisch:
GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
umgeht weiterhin sowohl den stillen Crash der älteren Builds als auch den Startup-Guard ab 8.3.1. Die ursprüngliche Analyse beschreibt, warum der Crash passiert — daran hat sich nichts geändert, nur an der Art, wie MongoDB ihn meldet.
Update (September 2026): MongoDB auf Linux Kernel 7 offiziell erklärt
Inzwischen hat MongoDB die Ursache offiziell benannt. Laut den Release Notes zu MongoDB 8.0 liegt die Inkompatibilität zwischen den Linux-Kerneln 6.19 bis 7.0.13 und der in mongod mitgelieferten TCMalloc-Version; deshalb stoppt der Server auf diesen Kerneln beim Start. Das Ticket SERVER-121912 beschreibt den Mechanismus genauer: TCMalloc verletzt die rseq-ABI des Kernels. Außerdem nennen die Release Notes ein Ende: Ab Linux Kernel 7.0.14 gilt die Inkompatibilität als aufgehoben.
Für die Praxis heißt das: Wer MongoDB 8 auf Linux Kernel 7 betreibt, hat jetzt zwei Wege. Entweder der Kernel steigt auf 7.0.14 oder neuer, dann läuft mongod ohne Workaround. Oder der Workaround aus diesem Artikel bleibt im Docker-Compose, bis das Kernel-Update durch ist. Unsere Shadow-Stack-Analyse bleibt eine Beobachtung an unserem System; ob der Fiber-Pivot ein zweiter Auslöser ist oder derselbe rseq-Konflikt in anderer Erscheinung, haben wir nicht nachgemessen.
MongoDB 8 auf Linux Kernel 7: der Restart-Loop, der keiner sein sollte
Neuer Rechner, neues Kernel-Update — Ubuntu 26.04 LTS mit Linux 7.0.0 auf einem Ryzen 9000. docker compose up, alles grün. Zehn Minuten später: der mongodb-Dev-Container steht bei restartCount: 314. Takt: alle 29 Sekunden ein Crash. Exit-Code 139 — also SIGSEGV.
Gleichzeitig fallen Testcontainer-basierte Integration-Tests um, immer mit demselben Muster: “MongoDB container is not running. exitCode=139”. Mal läuft der Test durch, mal nicht. Flaky, würde man sagen.
Allerdings ist das nicht flaky. Das ist reproduzierbar kaputt. Du siehst es nur nicht sofort, weil MongoDB leise stirbt. Kein Stack Trace im Log. Kein Eintrag in dmesg. Nichts. Der Prozess ist einfach weg.
Neckar IT
Solche Probleme lösen wir täglich.
Wir bauen Software, die genau solchen Details standhält — mit einem Team, das Technik ernst nimmt. Lust, mitzubauen?
Team kennenlernenDie CPU hält MongoDB auf Linux Kernel 7 für einen Angreifer
AMD Zen 4 und Zen 5 unterstützen CET Shadow Stacks — eine Hardware-Security-Funktion, die einen zweiten, CPU-verwalteten Stack mitführt. Bei jedem RET wird geprüft: Zeigen der normale Stack und der Shadow Stack auf dieselbe Rücksprungadresse? Wenn nicht — Process kill. Return-Oriented-Programming-Exploits laufen damit ins Leere.
Linux-Kernel ≥ 6.19 aktiviert das Feature per user_shstk standardmäßig für User-Space. Ubuntu 26.04 LTS bringt Kernel 7.0.0 mit. Sprich: Auf jedem halbwegs aktuellen AMD-Rechner ist Shadow Stack jetzt scharfgeschaltet.
Und jetzt kommt MongoDB 8 ins Spiel. MongoDB 8 nutzt intern Fibers — eine User-Space-Scheduling-Variante, die bei jedem Context-Switch den Stack-Pointer auf eine andere Speicheradresse umlegt (klassisch via Boost.Context / jump_fcontext). Für die CPU sieht das nicht nach Fiber aus. Das sieht nach Angriff aus. Der normale Stack zeigt woanders hin als der Shadow Stack. CPU killt Prozess.
Der fiese Teil dabei: Die Stack-Pivots passieren erst, wenn die Hintergrund-Threads LogicalSessionCacheReap und LogicalSessionCacheRefresh zum ersten Mal laufen. Das ist nach ungefähr 30 Sekunden. Deshalb der 29-Sekunden-Takt im Restart-Loop. Deshalb auch kein Stack Trace — CET killt sauber per SIGSEGV, bevor MongoDB irgendwas loggen kann. Und dmesg sagt auch nichts, weil das Kill ein ganz normaler SegFault aus Kernel-Sicht ist.
MongoDB 6.0 und 7.0 haben ein anderes Scheduling-Modell und sind nicht betroffen. Exakt diese Eigenheit von MongoDB 8 trifft die neue Hardware-Security.
Der Fix: GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK als Environment-Variable. Damit deaktiviert glibc Shadow Stacks für den mongod-Prozess. Andere Prozesse im System behalten ihren Schutz.
Eine Zeile im Docker-Compose. Das war’s.
Neckar IT
Klingt nach Ihrer Art zu arbeiten?
Wir bauen Software, die genau solchen Details standhält — mit einem Team, das Technik ernst nimmt. Lust, mitzubauen?
Team kennenlernenWarum Silent Kills so teuer sind
Zwischen “Container crasht” und “Ich weiß, warum” lagen trotzdem mehrere Stunden. Nicht weil das Problem kompliziert ist — sondern weil es keine Spur hinterlässt. Exceptions landen im Log, OOM-Kills tauchen in dmesg auf, ein gewöhnlicher SegFault schreibt einen Stack Trace. Shadow-Stack-Kills machen nichts davon: Die CPU terminiert den Prozess, der Kernel sieht einen normalen SegFault, und niemand schreibt irgendwo hin, warum.
Die Standard-Werkzeuge — docker logs, journalctl, strace — zeigen nichts. Der Prozess war da, der Prozess ist weg, dazwischen liegt ein schwarzes Loch. Bis dir einfällt, nach dem Exit-Code in MongoDB-Bug-Datenbanken und obskuren Kernel-Trackern zu suchen. Für die CPU ist ein legitimer Fiber-Pivot nicht von einem Angriff zu unterscheiden — sie sieht den Kontrollfluss, nicht die Absicht.
Per-Container fixen, nicht per Host
Die naheliegende Reaktion auf so einen Bug: Host-Config anpassen. /etc/docker/daemon.json editieren, /etc/security/limits.conf hochdrehen, systemd-Unit ändern, neu starten. Klassisch. Funktioniert. Dokumentieren. Ab in die Admin-Runbook.
Allerdings skaliert das schlecht. Jeder Dev muss den Fix lokal einspielen, jeder neue Laptop auch, CI-Runner sowieso. Und wenn der Fix irgendwann nicht mehr nötig ist — weil MongoDB den Fiber-Code umschreibt oder Docker die Defaults hochsetzt —, muss man überall zurückrollen. Unsichtbarer Status pro Host. Neue Form von Shadow Tech Debt.
Bessere Lösung: Fix ins Docker-Compose, ab in den Branch, Merge Request durch. Zwei Dateien:
docker-compose.template.yml—GLIBC_TUNABLESfür den mongodb-ServiceSharedMongoContainer.kt— dasselbe für die Testcontainer-basierten Tests, perwithEnv()
Das war’s. Danach hat jeder, der git pull macht, den Fix. Neue Laptops — kein Setup. CI-Runner — Fix inklusive. Und wenn’s irgendwann nicht mehr nötig ist: zwei Dateien editieren, MR, fertig. Der Status liegt im Repo, nicht im Admin-Gedächtnis — reviewt, in Git Blame auffindbar, genauso leicht wieder rausnehmbar wie reingesetzt.
Was man davon mitnehmen kann
- Neue Hardware-Security-Features sind per Default aktiv. Shadow Stacks, Intel CET, Memory Tagging — das alles rollt still in aktuelle Kernel. Vorhandener Code, der clever mit Stack oder Speicher umgeht, kann plötzlich krachen. Fibers, JIT-Compiler, bestimmte Garbage Collectors. Wer schon länger am gleichen Rechner arbeitet, merkt das erst, wenn er auf ein neues Setup wechselt.
- Silent Kills brauchen andere Debug-Strategien. Standard-Logs helfen nicht. Hilft: Bug-Datenbanken nach dem Exit-Code durchsuchen,
strace -faufs Binary, Kernel-Logs mitjournalctl -kgegen den exakten Timestamp. Und: Eigene Reproduktion bauen, die schnell crasht. Ohne Repro bist du blind. - Workarounds gehören ins Repo. Nicht in die Host-Config. Jede Änderung, die außerhalb des Repos stattfindet, ist unsichtbar, lässt sich nicht reviewen und rollt nicht auf neue Rechner aus. Ein
GLIBC_TUNABLESim Docker-Compose ist reproduzierbar. EinGLIBC_TUNABLESin/etc/docker/daemon.jsonist eine Zeitbombe.
Fazit
Ein SIGSEGV, kein Stack Trace, ein Exit 139: So stirbt MongoDB 8 auf Linux Kernel 7. Schuld ist aus unserer Sicht eine neue CPU-Security, die den Fiber-Switch für einen Angriff hält. Reproduzierbar kaputt, per Ein-Zeiler lösbar — nur eben erst, wenn man versteht, was passiert.
Die technische Lektion ist also trivial. Die eigentliche: Wenn etwas ohne Fehlermeldung um die Ohren fliegt, liegt das Problem fast nie da, wo du zuerst suchst. Und der Fix gehört ins Repo, nicht in die Host-Config — sonst produzierst du dir die nächste Form von Shadow Tech Debt selber.
Quellen:
- MongoDB BugID 3392546 — findbugzero.com
- Sky1-Linux/linux-sky1 Issue #15 — github.com
- Linux Kernel Documentation — x86_64/shstk.rst
- MongoDB 8.0 Release Notes, Abschnitt zur Linux-Kernel-Inkompatibilität — mongodb.com
- MongoDB Jira SERVER-121912 (Upgrade tcmalloc to include rseq bug fix) — jira.mongodb.org