
Fil-C: sicurezza della memoria completamente compatibile per C e C++
Fil-C è un'implementazione di C e C++ con sicurezza della memoria fanaticamente compatibile. Molti software si compilano ed eseguono con Fil-C senza o con minime modifiche. Tutti gli errori di sicurezza della memoria vengono catturati come panic di Fil-C. Fil-C ottiene questo risultato utilizzando una combinazione di garbage collection concorrente e capability invisibili (ogni puntatore in memoria ha una capability corrispondente, non visibile allo spazio di indirizzamento C). Ogni operazione C fondamentale (come vista in LLVM IR) viene verificata rispetto alla capability. Fil-C non ha istruzioni unsafe e ha solo un FFI limitato verso codice non sicuro.
Fil-C è speciale perché:
Fil-C raggiunge la piena sicurezza senza vie di fuga. Non esiste una parola chiave unsafe in Fil-C che possa essere usata per disattivare le protezioni. Il linking a codice non sicuro è severamente limitato.
L'approccio basato su capability di Fil-C raggiunge un livello di sicurezza simile a quello delle capability hardware come CHERI, tranne per il fatto che funziona su hardware standard (X86_64 o ARM64).
Fil-C è progettato per impedire che i bug di sicurezza della memoria vengano usati per lo sfruttamento, piuttosto che semplicemente segnalarli abbastanza spesso da trovare i bug. Questo rende Fil-C diverso da AddressSanitizer, HWAsan o MTE, che possono tutti essere aggirati dagli attaccanti. La differenza chiave che rende possibile tutto ciò è che Fil-C è basato su capability (quindi ogni puntatore sa a quale intervallo di memoria può accedere e come può accedervi) piuttosto che basato su tag (dove gli accessi ai puntatori sono consentiti se colpiscono memoria valida).
Dal punto di vista dell'utente del linguaggio, Fil-C è semplicemente C e C++ con le estensioni di GCC/clang. È più probabile che non che il vostro programma o libreria C o C++ preferito si compili in Fil-C senza modifiche. Il compilatore Fil-C è basato su clang 20.1.8, quindi supporta C17 e C++20.
Il compilatore (clang + LLVM) è coperto da LLVM-LICENSE.txt. Il runtime è coperto da PAS-LICENSE.txt (vedere libpas/LICENSE.txt nella distribuzione del sorgente). Nel caso della classica distribuzione Fil-C basata su musl, la libc musl è coperta da MUSL-LICENSE.txt (vedere projects/yolomusl/COPYRIGHT e projects/usermusl/COPYRIGHT nella distribuzione del sorgente). Nel caso della distribuzione /opt/fil, glibc è coperta da glibc-LICENSE.txt, e tutti gli altri programmi inclusi sono coperti dai rispettivi file -LICENSE.txt. Le librerie C++ (libc++/libc++abi) sono coperte da LLVM-LICENSE.txt.
È possibile recuperare il sorgente del compilatore, del runtime, di libc++/libc++abi, della libc (musl e glibc) e di tutti i programmi inclusi da github. La distribuzione del sorgente include anche molti programmi aggiuntivi che sono stati portati a Fil-C nelle directory projects/ e pizlix/, e hanno licenze varie. La distribuzione /opt/fil include build di una varietà di programmi aggiuntivi e le loro licenze sono in additional-licenses/ in quella distribuzione.
Fil-C funziona solo su Linux/X86_64 o Linux/ARM64.
Le versioni precedenti funzionavano su Darwin/ARM64 e FreeBSD, ma ora mi sto concentrando solo su Linux perché mi permette di fare un lavoro più fedele nell'implementazione della libc. Non c'è nulla che impedisca fondamentalmente a Fil-C di funzionare su altre architetture o sistemi operativi diversi da Linux.
Se avete scaricato i binari di Fil-C, eseguite:
./setup.sh
Questo ha un effetto diverso a seconda della distribuzione binaria che avete selezionato:
Nel caso della classica distribuzione basata su musl
(filc-0.684-linux-x86_64.tar.xz o filc-0.684-linux-aarch64.tar.xz), questo
configura Fil-C per funzionare nella directory corrente.
Nel caso della distribuzione /opt/fil basata su glibc
(optfil-0.684-linux-x86_64.tar.xz), questo configura Fil-C in /opt/fil.
Se avete scaricato il sorgente di Fil-C, eseguite:
./build_all_fast.sh
Poi potrete usare Fil-C da questa directory.
La distribuzione binaria di Fil-C viene fornita con musl come libc. Usare
./build_all_fast.sh nella distribuzione del sorgente costruisce anche Fil-C usando musl.
Se state usando il sorgente, potete anche:
./build_all_fast_glibc.sh - costruisce una configurazione simile ma con glibc 2.40 come
libc.
./build_all.sh - build completa basata su musl (costruisce anche molto software che
è stato portato a Fil-C).
./build_all_glibc.sh - build completa basata su glibc (costruisce ancora più software
che è stato portato a Fil-C).
cd pizlix && sudo ./build.sh - costruisce la distribuzione Linux Pizlix.
cd optfil && sudo ./build.sh - costruisce la distribuzione /opt/fil.
Molti pacchetti software funzionano in Fil-C senza o con minime modifiche, inclusi quelli grandi come openssl, CPython, SQLite e molti altri. Fil-C è abbastanza potente da supportare un userland Linux completamente sicuro per la memoria.
Fil-C ha pieno supporto per C e C++ più quasi tutte le estensioni che clang 20 supporta. Fil-C ha un eccellente supporto per atomics e intrinsics SIMD, per esempio.
Fil-C cattura tutte le cose che rendono difficile la sicurezza della memoria in C, come:
Out-of-bounds sull'heap o sullo stack.
Use-after free (anche su heap o stack).
Type confusion tra puntatori e non-puntatori.
Errori di tipo derivanti dal linking.
Errori di tipo derivanti dall'uso improprio di va_lists.
Pointer races.
System calls. Tutti i buffer passati alle system call vengono controllati per bounds e tipo.
Molte altre cose.
Fil-C viene fornito con una libc POSIX ragionevolmente completa e supporta anche funzionalità
complesse come thread, gestione dei segnali, mmap/munmap, longjmp/setjmp,
e eccezioni C++.
Potete saperne di più su Fil-C visitando il sito web.
Potete anche inviarmi un'e-mail: [email protected]
Seguimi su Twitter.
Segnalate problemi su GH.