Saturday’s Talks: l’open-source è nulla senza la riproducibilità delle build

8 hours ago 30

È open-source, chiunque può leggere il codice dall’inizio alla fine e quindi il pacchetto è fidato

Alzi la mano chi ha sentito almeno una volta questa frase pronunciata con leggerezza, magari con orgoglio nerd. Bene, ora tenetela alzata se ci avete creduto fino in fondo.

Come molti di voi sapranno già, la realtà è sempre più complicata della teoria. Oggi scenderemo insieme nella tana del Bianconiglio (e se avete colto la citazione, probabilmente avrete qualche capello bianco).

Il primo problema è quello banale: l’affermazione di cui sopra assume che chiunque sia in grado o abbia energie, voglia e tempo per leggersi migliaia o centinaia di migliaia di righe di codice e che abbia anche le capacità di scovare parti di codice problematiche o bug accidentali e non che aggiungano una backdoor, uno spyware o un ransomware al pacchetto che si sta installando. Situazione ancora meno proponibile con software moderni e complessi come Chromium e Firefox, per esempio, che consistono in più di 30 milioni di righe di codice.

Anche nel migliore dei casi in cui qualcuno abbia controllato il codice in qualche momento della sua storia, non si può controllare tutto e tutte le relative quotidiane patch, anche al netto del fatto che chiunque di noi potrebbe elencare 1000 cose più interessanti che fare l’audit di una libreria o di un browser tra cui anche maratone di film con Nicolas Cage o, peggio ancora, il taglio delle unghie dei piedi.

Se anche si costituisse un intero team di ricercatori pompati di caffeina e altri poco chiari intrugli a fare un audit approfondito, questo non basterebbe, perché il software è sempre in continua evoluzione con patch, bugfix e quant’altro, con nuovi commit e nuove righe di codice che si aggiungono e rimuovono di continuo nelle migliaia di pacchetti che compongono ogni distribuzione Linux. Parliamo di una valanga di nuovo codice, ogni giorno.

Il secondo problema è l’assumere che qualcun altro l’abbia già fatto, da qualche parte nel mondo, e che quindi stiamo eseguendo un programma il cui codice è già stato letto da qualcuno, cosa non necessariamente vera. Chi sarebbe, questo qualcuno? Linus Torvalds in persona? Qualche supereroe che non dorme la notte e poi il giorno va comunque a lavorare?

Il terzo, grande, problema, focus della discussione di oggi, è che non tutte le build sono riproducibili.

In soldoni, se diamo lo stesso codice sorgente a 2 o 3 persone o se usiamo dispositivi, toolchain e sistemi operativi diversi per passare da un sorgente a un binario, è molto probabile che i checksum dei pacchetti risultanti non coincidano tra di loro, per ragioni “fisiologiche” al processo di compilazione ma il risultato sarebbe il medesimo: checksum diversi.

Purtroppo, se i pacchetti non coincidono nonostante il codice iniziale sia identico, non coincideranno neanche se ci si inserisce del malware “post-codice” o se vengono compilati da un codice diverso. Il concetto di “similitudine” non esiste per le checksum.

Non riuscire a distinguere se un pacchetto è diverso per ragioni “normali” o per ragioni malevole è un gran bel problema. Chi ci garantisce, a questo punto, che il pacchetto binario sia un derivato del codice sorgente e non di tutt’altro codice, magari nocivo o che possa trafugare i nostri dati in background?

E’ qui che entra in gioco il concetto di Reproducible Builds. In buona sostanza, se prendiamo lo stesso identico codice sorgente e lo compiliamo su macchine diverse e con strumenti leggermente diversi, i risultati (i famosi file binari che usiamo e\o installiamo) dovranno essere identici, bit per bit, e risultare in file con checksum identici.

Così facendo, possiamo evitare di preoccuparci di un aspetto fondamentale e spesso trascurato: potremo essere sicuro che il pacchetto che abbiamo sotto mano sia derivato effettivamente dal codice sorgente in oggetto, che è già un primo passo verso il potersi fidare di ciò che eseguiamo sulle nostre macchine. Del resto, senza che molti di voi ci facciano caso, stanno già implicitamente ponendo una forte fiducia, oltre che sugli autori del programma, anche sui package maintainer. Per dirne una, su Arch, un solo maintainer pacchettizza il 42% di tutta la distro.

Ok, quindi abbiamo la soluzione, no? Non così in fretta.

Compilare un programmino in C da 500 righe di codice è una cosa ben diversa dal produrre un binario per software moderno e complesso (vedi l’esempio di un browser fatto sopra) che può incorporare più linguaggi, più librerie e dipendenze, ordini non deterministici, parametri di build differenti, parametri di ottimizzazione differenti e quant’altro.

Chiunque abbia avuto la fortuna o la sfortuna di smanettare con Gentoo, avrà ben familiare il concetto delle USE\CFLAGS, ovvero quelle opzioni e parametri che possiamo scegliere a tempo di compilazione per molti dei nostri pacchetti, magari per aggiungere features non presenti nelle compilazioni standard, rimuovere feature che sapremo già non usare o scegliendo di ottimizzare per l’architettura del processore che si ha sotto mano. Queste libertà sono una delle motivazioni più “gustose” per chi compila il software da sé.

Se avete sentito parlare, ad esempio, di librerie come ffmpeg o audacity, sarete anche ben familiari con il fatto che distribuzioni Linux diverse avranno scelto flag di compilazione diverse, per i motivi più svariati. I programmi sono identici ma non lo sono i risultati finali (e i relativi checksum).

Ricordate, ora, le 30 milioni di righe di codice di un browser moderno di cui parlavamo sopra? Ecco, questo dovrebbe rendere almeno una vaga idea di quante parti in movimento possano esserci nel retroscena del trasformare dei file di testo (il codice sorgente) in un file binario pronto per l’uso.

A che punto siamo, quindi, con il concetto? Stando a reproducible-builds.org o Arch Linux Reproducible Status, ci sono dei progressi, ma non siamo ancora al 100% e possiamo facilmente dedurre che basterebbe anche un solo pacchetto (specie se fornito di default con la distribuzione) a trasformare l’intera distro in uno spyware o robaccia simile.

Interessante anche una proposta emersa la settimana scorsa da parte della community Fedora di puntare addirittura a una situazione in cui il 99% di pacchetti sia riproducibile. Se approvata, se un pacchetto non è riproducibile per n motivi, sarà possibile considerare questa cosa un bug.

Passi nella direzione giusta, quindi, ma una volta arrivati a un già utopistico 100% di riproducibilità delle build in una distribuzione Linux, potremo quindi fidarci ciecamente?

Ecco, avete indovinato: no, non ancora, anche se questo non deve impedirci di migliorare ciò che è migliorabile.

Nel 1984, uno dei padri di Unix, Ken Thompson, pubblicò un saggio chiamato “Reflections on Trusting Trust”, che possiamo tradurre come un “Riflessioni sul fidarsi della fiducia stessa”. In esso, si menzionava, tra le tante cose, la possibilità di introdurre una backdoor a livello di compilatore, come una “firma” nascosta e non richiesta, non presente nel codice sorgente originale, ma presente in ogni binario realizzato con lo stesso compilatore.

Potremmo anche fare lunghe digressioni sul quanto vi fidate del vostro hardware, sulle questioni Intel ME o sull’AMD PSP, scatole nere che vi ritrovate a bordo senza aver controllo su cosa facciano, ma ciò non significa che non si debbano migliorare i processi su cui abbiamo almeno qualche forma tangibile di controllo.

Insomma, la sicurezza assoluta può apparirci come una chimera, ma ci sono dei processi che, oggettivamente, fanno acqua da tutte le parti e uno di questi è, appunto, il fatto che senza reproducible builds, da nessuna parte sta scritto che quel binario e quel codice sorgente siano lo stesso programma e facciano la stessa cosa.

Se siete diventati un po’ più paranoici di prima ma, soprattutto, se smetterete di utilizzare il pretesto “è open-source” per dire che un certo software è automaticamente fidato, allora avremo raggiunto il nostro obiettivo di oggi.

Appassionato di Linux e della cultura open-source da vent’anni, continuo a fare del mio meglio per diffondere tale filosofia e soprattutto condividere la conoscenza.

C’è sempre qualcuno da qualche parte nel mondo che sta avendo un problema che tu hai già risolto e, condividendo la soluzione, puoi fare la differenza.

Se quel qualcuno sei tu, chiedi pure alla community. La trovi ovunque, ad esempio su reddit.com/r/italyinformatica, reddit.com/r/fedora, reddit.com/r/debian, reddit.com/r/ubuntu, reddit.com/r/archlinux, reddit.com/r/linux, sui forum specifici delle distro oppure sulle loro wiki.

Perchè nessun problema andrebbe risolto più di una volta.

[https://it.linkedin.com/in/john-toscano]

Read Entire Article