====== Ausliefern ====== Ein Lyx-Programm ist eine einzelne, statisch gelinkte Datei ohne Laufzeitumgebung. Das macht das Ausliefern einfach — und verschiebt die Fragen: nicht „welche Bibliotheken müssen mit?", sondern „für welches Ziel, mit welchen Rechten, und wie beweise ich, dass es dasselbe Binary ist?". → [[lyx_-_programmiersprache:guides:crosscompiling|Cross-Compilation]] · [[lyx_-_programmiersprache:sprache:capabilities|Capabilities]] · [[lyx_-_programmiersprache:guides:lpm-workflow|lpm]] ---- ===== Was herauskommt ===== lyxc app.lyx -o app file app ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked Kein Interpreter, keine libc-Pflicht, kein Garbage Collector — die Datei läuft auf jedem Linux mit passender Architektur. Ein Hello-World liegt bei rund 100 KB, ein Programm mit Dateizugriff und Capabilities im Beispiel unten bei 206 KB. **Ausnahme:** Wer ''extern fn … link "lib…so"'' benutzt, verlangt diese Bibliothek auf dem Zielsystem. Das ist die einzige Abhängigkeit, die entstehen kann — und sie steht im Quelltext. ---- ===== Für welches Ziel ===== lyxc app.lyx -o app # Linux x86-64 lyxc app.lyx --target=win64 --format=pe -o app.exe # Windows lyxc app.lyx --target=arm64 -o app_arm64 lyxc app.lyx --target=riscv -o app_riscv lyxc app.lyx --target=macosx64 --format=macho -o app_mac Alle Ziele entstehen aus derselben Quelle, ohne Cross-Toolchain. Die vollständige Liste samt Einschränkungen steht im [[lyx_-_programmiersprache:guides:crosscompiling|Cross-Compilation-Guide]]; für Oberflächen kommt die Backendwahl über den Include-Pfad dazu ([[lyx_-_programmiersprache:vega:guides:portabel|Vega: portabel bauen]]). ---- ===== Rechte festlegen: @capabilities ===== @capabilities([system.exit, system.memory.heap, fs.read]) import std.io; import std.fs; import std.alloc; fn main(): int64 { var buf: int64 := alloc(256); var n: int64 := ReadFile("/etc/hostname", buf as pchar, 255); if (n > 0) { PrintLn("gelesen"); } else { PrintLn("nicht lesbar"); } free(buf, 256); return 0; } Aus der Deklaration entsteht ein **seccomp-Filter**. Das Audit im Build zeigt, was daraus wurde: Explizite Capabilities: + W^X (RX-Code / RW-Daten getrennt — zwei PT_LOAD) + RELRO (kein GOT/PLT-Angriffsziel — statisches ELF) + seccomp (SECCOMP_RET_KILL_PROCESS, 121 Regeln) Sicherheits-Score: 35/35 Und der Filter greift wirklich. Dasselbe Programm **ohne** ''fs.read'' in der Liste: vor dem Lesen Ungültiger Betriebssystemaufruf (Speicherabzug geschrieben), rc=159 Der Prozess stirbt beim nicht deklarierten Syscall. Für die Fehlersuche macht ''--seccomp-trap'' daraus ein ''SIGSYS'' **mit Syscall-Nummer**, statt stumm zu töten. **Ohne ''@capabilities'' gibt es keinen Filter** — das Audit sagt dann ''Capability-Modell: NONE''. Für ein ausgeliefertes Programm ist die Liste deshalb Pflichtprogramm, nicht Kür. ---- ===== Reproduzierbar bauen ===== * **''lyx.lock'' einchecken** und mit ''lpm install --offline'' bauen — ein Bau, der aus dem Netz nachlädt, ist nicht wiederholbar. * **Compilerversion festhalten** (''lyxc --version'') — sie gehört ins Build-Protokoll wie die Quellversion. * **Prüfsumme des Binaries** bilden und mitliefern; bei gleicher Quelle und gleicher Compilerversion entsteht dasselbe Ergebnis. * **Keine Zeitstempel oder Pfade** ins Programm einbetten, wenn die Prüfsumme stabil bleiben soll. ---- ===== Was mit ausgeliefert werden muss ===== ^ Fall ^ Mitliefern ^ | Reines Rechenprogramm | nur die Datei | | ''extern fn … link "libfoo.so"'' | die Bibliothek muss auf dem Ziel vorhanden sein | | Vega-Anwendung | nichts zusätzlich — X11 bzw. Win32 stellt das System | | Eigene Themes (''.vtheme'') oder Formulare (''.lfm'') | die Dateien, relativ zum Arbeitsverzeichnis | | Daten, die zur Laufzeit gelesen werden | dieselbe Überlegung — und die passende Capability | ---- ===== Vor der Auslieferung ===== - ''lyxc --version'' notieren, ''lpm install --offline'', Bau aus sauberem Stand. - Testreihe laufen lassen ([[lyx_-_programmiersprache:guides:testen|Testen]]). - Audit ansehen: Steht ''seccomp'' dort? Ist der Score, was er sein soll? - ''file'' auf das Ergebnis: richtiges Format, richtige Architektur, ''statically linked''. - Auf dem Zielsystem starten — nicht nur auf der Entwicklungsmaschine. - Prüfsumme bilden und mit dem Build-Protokoll ablegen. ---- ===== Fallstricke ===== * **Capabilities zu knapp.** Der Fehler zeigt sich erst beim seltenen Pfad — Tests laufen unter demselben Filter wie die Auslieferung. * **Capabilities zu weit.** ''system.unsafe.*'' hebt den Sinn der Übung auf. * **''--target'' vergessen.** Ein ELF auf einem Windows-Ziel fällt sofort auf, ein x86-64-Binary auf ARM erst beim Kunden. * **Relative Pfade.** Programme, die Dateien neben sich erwarten, brauchen eine feste Annahme über das Arbeitsverzeichnis. Letzte Aktualisierung: 2026-08-19 — Beispiel, Audit-Ausgabe und die Wirkung des seccomp-Filters mit ''lyxc 1.1.3I'' nachgemessen.