====== std.meta_safe ====== Sicherer Post-Patching Runtime-Verifier: Liest die ''.meta_safe''-ELF-Section aus ''/proc/self/exe'', re-berechnet CRC32-Prüfsummen für jede Code-Page (4 096 Bytes) und meldet, ob das Binary seit dem Kompilieren unverändert ist. Die Section wird vom Compiler-Pass ''ms_appendMetaSafe()'' automatisch erzeugt, wenn ''%%--%%meta-safe'' gesetzt ist — kein manuelles Linking erforderlich. Auf x86_64 steht ein optimierter Fast-Path zur Verfügung. → [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:alloc|std.alloc]] > **Was diese Unit prüft — und was nicht** (gemessen mit lyxc 1.1.14A): > > * Sie liest die **Datei** ''/proc/self/exe'' und rechnet über deren Inhalt. Erkannt wird damit eine **Manipulation des Programms auf dem Datenträger** (Post-Patching). Ein Bit-Flip in einer bereits geladenen Codeseite im RAM wird davon **nicht** erfasst — für den SEU-Schutz, den die Safety-Guides beschreiben, reicht das nicht ([[https://github.com/SEOLizer/LyX-Compiler/issues/1879|#1879]]). > * Sie läuft **nur, wenn das Programm sie selbst ruft**. Einen periodischen Sweep gibt es hier nicht — den bringt seit 1.1.15A ''@integrity(mode: scrubbed, interval: …)'' mit, und der prüft die **geladenen** Codeseiten, nicht die Datei (→ [[lyx_-_programmiersprache:guides:do-178c:memory-scrubbing|Memory Scrubbing]]). Zwei Wege, zwei Fragen. > * Sie **erkennt**, sie **korrigiert nicht**. Die Hashtabelle liegt inzwischen im Format v2 (''METASAF2'') **dreifach** ab, sodass die Mehrheit über einen verfälschten Eintrag entscheidet ([[https://github.com/SEOLizer/LyX-Compiler/issues/1877|#1877]]). > > Nachgemessen: ohne ''%%--%%meta-safe'' liefert ''MetaSafeVerify()'' ''-1'' (Sektion fehlt), mit ''%%--%%meta-safe'' ''0''; nach dem Kippen eines einzelnen Byte im Codebereich der Datei wieder ''-1''. ---- ===== Konzept ===== Der Lyx-Compiler legt beim Build eine ELF-Section ''.meta_safe'' an, die für jede 4 096-Byte-Page im ''.text''-Segment einen Eintrag enthält: ^ Offset ^ Größe ^ Inhalt ^ | 0 | 4 Bytes | Magic ''0x4D455441'' (''„META"'') | | 4 | 4 Bytes | Anzahl Pages (''pageCount'') | | 8 | 8 Bytes | Tatsächliche ''.text''-Länge in Bytes (''codeLen'') | | 16 + n×8 | 4 Bytes | Page-Offset von ''.text''-Start | | 16 + n×8 + 4 | 4 Bytes | Gespeicherter CRC32 dieser Page | ''MetaSafeVerify'' öffnet ''/proc/self/exe'', liest das gesamte Binary, lokalisiert die ''.meta_safe''-Section über den ELF-Section-Header-Table, re-berechnet den CRC32 jeder Page und vergleicht mit den gespeicherten Werten. ---- ===== Funktionen ===== ^ Signatur ^ Beschreibung ^ | ''MetaSafeVerify(): int64'' | Prüft alle Code-Pages. Gibt ''0'' zurück wenn alle CRC32-Prüfsummen stimmen, ''−1'' bei Fehler (korrupte Page, fehlende Section, kein Lesezugriff auf ''/proc/self/exe''). | | ''MetaSafeGetPageHash(pageIdx: int64): int64'' | Gibt den gespeicherten CRC32-Wert für Page ''pageIdx'' (0-basiert) zurück, oder ''−1'' wenn ''pageIdx'' außerhalb des gültigen Bereichs liegt. | ---- ===== Verwendung ===== ==== Integrity-Check beim Start ==== import std.meta_safe; import std.io; fn main(): void { var r := MetaSafeVerify(); if (r != 0) { PrintLn("WARNUNG: Binary-Integrität verletzt!"); // Sicherheitsreaktion: Abbruch, Logging, Alert … exit(1); } // Normaler Programmstart … } ==== Page-Hash abrufen (Diagnose) ==== import std.meta_safe; import std.io; fn PrintPageHashes(count: int64): void { var i: int64 := 0; while (i < count) { var crc := MetaSafeGetPageHash(i); if (crc < 0) { break; } Print(StrConcat(StrConcat("Page ", IntToStr(i)), ": CRC32 = 0x")); // CRC als Hex ausgeben … PrintLn(IntToStr(crc)); i := i + 1; } } ==== Periodische Laufzeit-Prüfung ==== import std.meta_safe; import std.thread; fn IntegrityWatchdog(): void { // In einem separaten Thread periodisch prüfen while (1 == 1) { if (MetaSafeVerify() != 0) { // Alarm schlagen … } sleep(30000); // alle 30 Sekunden } } ---- ===== CRC32-Algorithmus ===== Die verwendete Polynomkonstante ist ''0xEDB88320'' (ISO 3309, PKZIP-kompatibel). Die Implementierung spiegelt exakt den Compiler-seitigen ''ms_crc32'': // CRC32 über len Bytes ab data: // crc = 0xFFFFFFFF // für jedes Byte b: crc = (crc >> 1) ^ (0xEDB88320 falls LSB gesetzt) // Rückgabe: crc ^ 0xFFFFFFFF ---- ===== Hinweise ===== * ''MetaSafeVerify'' öffnet ''/proc/self/exe'' und liest das **gesamte Binary** in den Heap — bei großen Binaries (> 10 MB) entsprechend Speicher einplanen. * Die Funktion ist nicht reentrant-sicher: mehrfache parallele Aufrufe aus verschiedenen Threads sind zu vermeiden. * ''MetaSafeVerify'' gibt ''−1'' zurück wenn die ''.meta_safe''-Section fehlt (d. h. das Binary wurde nicht mit ''%%--%%meta-safe'' gebaut oder der Abschnitt wurde gestripped). * Für Produktions-Deployments empfiehlt sich ein einmaliger Aufruf beim Programmstart; ein laufender Watchdog-Thread erhöht die Schutzwirkung gegen Live-Patching-Angriffe. * Die Section-Suche parst den ELF-Section-Header-Table direkt (keine externen Bibliotheken). Unterstützt werden ELF64-Binaries auf x86-64 Linux (mit dediziertem Fast-Path) und AArch64 (generischer Pfad). * **Abgrenzung zu ''%%--%%integrity-check''**: ''%%--%%integrity-check'' (getriggert durch ''@integrity'') erzeugt ein festes 8232-Byte-Format mit drei CRC32-Kopien des gesamten Code-Segments (TMR-Schema). ''%%--%%meta-safe'' erzeugt eine variable Section mit einem CRC32 **pro 4 096-Byte-Page** — feiner granular, direkt zugänglich via ''MetaSafeGetPageHash''. * **Verifizierte Rückgabewerte** (Akzeptanztests): ''MetaSafeVerify()'' → ''0'' bei unverändert, ''−1'' bei korrumpierter Page oder fehlender Section; ''MetaSafeGetPageHash(invalidIdx)'' → ''−1''. ---- ===== Verwandte Units ===== * ''[[lyx_-_programmiersprache:units:alloc|std.alloc]]'' — Speicherverwaltung (wird intern von MetaSafeVerify genutzt) * ''[[lyx_-_programmiersprache:units:fs_ext|std.fs_ext]]'' — Fstat, Dateilesen Letzte Aktualisierung: 2026-09-05 ([[https://github.com/SEOLizer/LyX-Compiler/issues/1908|#1908]], gemessen mit lyxc 1.1.18A) — Kasten gezogen: der periodische Sweep existiert seit 1.1.15A über ''@integrity(mode: scrubbed)'' (prüft die geladenen Codeseiten, nicht die Datei), und die Hashtabelle liegt im Format v2 dreifach ab. Vorherige letzte Aktualisierung: 2026-06-06 Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen). Letzte Aktualisierung: 2026-08-30 — Reichweite der Prüfung gegen ''lyxc 1.1.14A'' nachgemessen und eingeordnet (Datei statt RAM, kein Sweep, keine Korrektur).