5 Punkte von GN⁺ 2025-01-24 | 4 Kommentare | Auf WhatsApp teilen
  • Ein Absturz, der nur auf ARM64 auftrat

    • Beim Portieren des Netzwerk-I/O-Codes von EdgeDB von Python nach Rust trat das Problem auf, dass Tests auf ARM64-CI-Runnern gelegentlich fehlschlugen.
    • Zunächst sah es wie ein Deadlock aus, tatsächlich stürzte jedoch der Prozess ab, und der Test-Runner erkannte dies nicht.
  • Erste Theorie

    • Um zu verstehen, warum das Problem nur auf ARM64 auftrat, wurden Unterschiede im Speichermodell berücksichtigt.
    • Das Speichermodell von Intel ist streng, während ARM ein schwächeres Speichermodell hat.
  • Debugging auf der CI-Maschine

    • Über AWS wurde direkt eine Verbindung zu einem ARM64-Runner hergestellt, um das Problem zu untersuchen.
    • Der Prozess stürzte ab und hinterließ einen Core Dump, der untersucht wurde, um die Ursache des Problems zu ermitteln.
  • Die tatsächliche Ursache: setenv und getenv

    • setenv ist in einer Multithread-Umgebung nicht sicher und kann im Zusammenspiel mit getenv Abstürze verursachen.
    • Es stellte sich heraus, dass die Neuzuweisung von Umgebungsvariablen die Ursache des Problems war.
  • Die Verbindung zu openssl-probe

    • Das Problem trat auf, als openssl-probe die Umgebungsvariablen SSL_CERT_FILE und SSL_CERT_DIR setzte.
    • Beim Setzen dieser Umgebungsvariablen durch Rusts rust-native-tls kam es zum Absturz.
  • Warum es nur auf ARM64 Linux auftrat

    • Der Absturz tritt nur auf, wenn mehrere Bedingungen gleichzeitig erfüllt sind; dazu gehören die Anzahl der Umgebungsvariablen und I/O-Fehler.
  • Lösung

    • Es wurde beschlossen, im rust-native-tls/openssl-Backend von reqwest auf rustls umzusteigen.
    • Das Rust-Projekt plant, Funktionen zur Umgebungskonfiguration als unsafe zu markieren, und das glibc-Projekt verbessert die Thread-Sicherheit von getenv.

4 Kommentare

 
carnoxen 2025-01-24

setenv ist nicht threadsicher, und C möchte das nicht ändern

Die Funktion setenv macht schon wieder Ärger.

 
y15un 2025-01-24

Ich würde den Titel als „Die Thread-Unsicherheit der C-Stdlib kann nicht einmal das ach so sichere Rust retten“ schreiben. :)

 
halfenif 2025-01-24

Ich habe es definitiv verstanden.

 
GN⁺ 2025-01-24
Hacker-News-Kommentar
  • In der nächsten Rust-Edition sollen Umgebungsvariablen-Setter als unsicher eingestuft werden. Das könnte Crates betreffen, die Konflikte auslösen

    • In der Rust-Standardbibliothek müssen set_var und remove_var in der Edition 2024 innerhalb eines unsafe {}-Blocks verwendet werden
    • Die aktuelle Dokumentation erwähnt zwar Sicherheitsprobleme, aber dass diese Funktionen ursprünglich als sicher eingestuft wurden, war ein Fehler
  • Ein Patch für glibc hat getenv sicherer gemacht, aber C erlaubt weiterhin direkten Zugriff auf die Umgebung und ist daher nicht vollständig sicher

    • Die Maintainer der C-Standardbibliothek sträuben sich dagegen, setenv threadsicher zu machen, aber zumindest sollte eine neue threadsichere API definiert werden
    • Der Maintainer von Musl ist offenbar nicht überzeugt, dass dieses Problem unlösbar ist
  • Unter Linux auf umgebungsbezogene Bugs zu stoßen, gilt fast als eine Art Initiationsritus

    • Linus und der Kernel gehen pragmatisch mit der Behebung von POSIX-Bugs um, aber glibc hinkt weiterhin hinterher
    • getenv_r() bereitzustellen, es mit setenv() zu synchronisieren und beim Kompilieren/Linken Warnungen auszugeben, hätte bei der Lösung des Problems helfen können
  • Konfiguration über Umgebungsvariablen war Teil der „12-factor app“-Bewegung, aber ich halte das für einen törichten Ansatz

    • Ich denke, Konfigurationsdateien wie YAML sind die bessere Alternative zu Umgebungsvariablen
  • CI-Maschinen, die auf Amazon AWS laufen, haben den Vorteil, dass sie echte Root-Benutzer bereitstellen

    • Es wirkt, als hätten wir die Fähigkeit verloren, Code lokal ohne Cloud und Container zu bauen und zu debuggen
  • Ein großartiger Artikel, der einem nicht offensichtlichen Bug auf den Grund geht

    • Solche detaillierten Berichte zur Fehlersuche kommen der Erfahrung, es selbst zu tun, am nächsten
  • env::set_var ist jetzt unsicher

    • In Single-Thread-Programmen kann es sicher aufgerufen werden
    • Unter Windows ist es sowohl in Single- als auch in Multi-Thread-Programmen immer sicher
    • In Multi-Thread-Programmen auf anderen Betriebssystemen ist es die einzige sichere Wahl, set_var oder remove_var nicht zu verwenden
  • Es erinnert an die Erfahrung, dass setproctitle in bestimmten Codebasen nicht funktionierte

    • Nach dem Import von numpy funktionierte setproctitle nicht mehr, weil sich durch einen Aufruf von getenv oder setenv während der numpy-Initialisierung die Adresse von environ geändert hatte