Sulla perdita dei dati dell’EXT4 e dei moti rivoluzionari

Un paio di settimane fa un utente aveva segnalato un grave problema relativo al nuovo file system ext4 recentemente incluso nel kernel Linux e dichiarato stabile.

La storia aveva dello straordinario perchè il nostro caro collega, in quanto utilizzatore di software libero, spiegava in un ticket di segnalazione del bug pubblicato su Launchpad come, dopo aver installato la versione alpha di kubuntu 9.04, abbia perso una grandissima quantità di dati in uno stop improvviso della macchina in questione.

In realtà i file erano presenti ma la loro dimensione era irrimediabilmente fissata sullo zero segno questo che non lascia ben sperare per il recupero degli stessi.

Da qui la polemica è divampata sulla rete in pochissimi secondi, le personalità più differenti si prodigavano nella denuncia del fatto che certamente ha sconvolto molti di coloro che utilizzano il software libero perchè ritenuto di qualità più alta.

Da che mondo è mondo se una cosa viene inclusa in una release del kernel significa che è matura, stabile e sicura.

Personalmente ho aspettato prima di fornire pareri ed eventualmente muovere critiche, volevo essere sicuro dei fatti e farmi una idea precisa dell’accaduto, analizzare per poi esporre realmente il problema è nella mia natura.

Passano i giorni, molto pochi in realtà, e vengo a sapere che il tizio che si occupa del file system ext4 ha rilasciato una patch per risolvere il problema, tale patch sarà disponibile nella release del kernel 2.6.30.

Decido allora di preparare una analisi semi approfondita della questione giusto per capire come e cosa è accaduto all’interno di quel disco rigido che ha dato il via alla piccola rivoluzione.

Genericamente quando un file viene alterato o modificato viene creato un primo file temporaneo (lo chiameremo A) che racchiude i nuovi dati e successivamente viene modificato l’indice dei file per far si che il vecchio file (lo chiameremo B) sia ora rintracciabile in un’altra locazione.

Questo processo da luogo a due condizioni; per prima cosa si ha un cambio dei metadati dei file all’interno del file system, viene creato un nuovo inode per il file temporaneo A che si andrà a scrivere e viene generata una nuova voce indice che punta al file A appena creato.

Una volta apportate le modifiche a questo nuovo file (A), e cambiato il suo nome, si reindirizza le informazioni di indice del vecchio file originario (B) a questa nuova posizione.

Ora si possono scrivere i dati e per fare ciò il sistema deve preparare una serie di blocchi sul disco sufficiente a stipare tutte le informazioni che si andranno a salvare.

In entrambe le tipologia di file system, parlo di ext3 e di ext4, vi è una protezione dei dati attraverso il sistema di journaling che effettua il commit, e quindi il cambiamento effettivo dei dati, solo quando le modifiche al file B sono terminate.

Un file di log si incarica di tenere traccia di tutte le attività svolte sul file, una volta che esse di possono considerare concluse vi è l’effettivo cambiamento delle informazioni.

Se in questa precisa fase si ha un calo della tensione del sistema è impossibile trovare all’avvio il nuovo file in quanto esso non è stato ancora creato e quindi, anche se ci dovessimo trovare nella condizione di aver già assegnato i parametri per l’indicizzazione del vecchio file alla nuova posizione, basterà un semplice riavvio del sistema per riportare tutto alla normalità pur avendo perso le nuove informazioni.

Purtroppo per noi però c’è una piccola ma sostanziale differenza tra i due file system (ext3 ed ext4), solo nel caso di un file system ext3, con opzione di mount in data=ordered (ovvero di ordinamento dei dati), i metadati vengono aggiornati dopo il commit delle nuove informazioni scritte nel file.

Questa operazione può richiedere fino a 5 secondi di tempo, in questo lasso di tempo le modifiche sono presenti solo nella cache del sistema ed è possibile che i blocchi di dati appena riservati alla nuova versione del file non presentino le modifiche apportate perchè facenti parte di un file appena eliminato o per altre cause.

In questa condizione dopo un crash del pc ci si ritroverebbe ad avere una versione vecchia o nuova delle informazioni a seconda che il down sia avvenuto prima o dopo la scrittura su disco.

Questo modo di operare permette di avere a disposizione sempre e comunque una versione dei dati che sia essa la più aggiornata o meno.

Ext4 dal canto suo invece opera in modo diverso in quanto ricorre alla assegnazione ritardata dei blocchi di memoria.

La scrittura dei dati quindi avviene in una fase successiva e secondaria alla chiusura delle modifiche sul file per permettere di ottimizzare il processo di scrittura reale su disco.

Questo metodo però lascia spazio ad una problematica ovvero quella di avere un file di dimensione 0 byte per non occupare blocchi di dati inutilmente fino al momento nel quale questo non venga scritto realmente su disco, momento che è ritardato nel tempo.

Se si verifica una interruzione dell’alimentazione in questa fase ci si ritrova nella condizione di avere un log di journaling dove l’operazione è stata già scritta come effettuata ma in realtà, proprio per la questione dell’allocazione ritardata dei blocchi su disco, essa non è realmente passata alla fase di commit.

Si crea una sorta di desincornizzazione tra cià che sono le modifiche scritte nel log del sistema di journaling e quelli che realmente sono i cambiamenti apportati.

La problematica sfocia quindi nella condizione di avere sia il vecchio che il nuovo file di dimensioni nulle.

Sicuramente un problema da sottolineare ma che trova riscontri simili in tutti quei file system che rispettano le direttive POSIX.

Lo stesso Ted T’so, curatore del progetto, ha dichiarato che la sicurezza dell’ext3 in queste occasioni non è una proprio caratteristica peculiare ma solo un effetto collaterale dovuto alla gestione dell’allocazione dei blocchi di dati del file system in questione.

Il problema si potrebbe manifestare soprattutto nel caso di applicazioni sviluppate seguendo come standard il comportamento anomalo del file system di precedente generazione.

La risoluzione dell’anomalia può essere affrontata in molti modi differenti, esattamente tre, ma la patch prontamente sviluppata da T’so prevede che l’azione di allocazione dei settori sia contemporanea a quella di scrittura delle informazioni (commit).

Non ci resta che attendere la release numero 2.6.30 per veder risolto il problema.

Personalmente ritengo che una situazione del genere sia difficile da reperire in situazione nelle quali il file system sia ospitato all’interno di dischi rigidi di un server visto che questo tipo di macchine sono (e devono essere) assistite da gruppi di continuità; è comunque vero che il problema andava scovato in anticipo e corretto prima di includere il supporto nel kernel Linux.

Ciao a tutti.

Sniffare porte usb con GNU/Linux, piccola trattazione tecnica

In modo teorico tutti i bus di comunicazione di un pc possono essere violati ed utilizzai per effettuare lo sniffing dei dati che li attraversano.

Dico in modo teorico perchè poi, all’atto pratico, sorgono delle difficoltà che difficilmente sono superabili se si ha a che fare con un computer custodito ed amministrato come si deve.

Non tutti i bus di comunicazione possono essere sniffati con la stessa facilità, per fare un piccolo esempio concreto si può dire che il bus usb è relativamente facile da compromettere mentre per il Firewire non ci sono problemi di alcun tipo vista la totale noncuranza in fase di progettazione per quel che riguarda la sicurezza della comunicazione rispetto a questo tipo di attacchi.

Uno strumento che ci permette di effettuare questa operazione sulle nostra care linux box prende il nome di usbmon.

Per prima cosa è necessario verificare se tutti i moduli del kernel necessari sono già presenti all’interno del nucleo da voi utilizzato, molto spesso essi sono già all’interno della vostra versione ma non vengono caricati di default e quindi occorre procedere alla loro attivazione attraverso un comando che impartiremo tramite shell:

1
2
mount -t debugfs none_debugs /sys/kernel/debug
modprobe usbmon

anche se so già che non ve ne è alcun bisogno vi ricordo che le operazioni di modprobe, ovvero di caricamento di moduli del kernel, vanno effettuate avendo i privilegi di amministratore del sistema.

Verifichiamo ora quali socket usb sono presenti attraverso il comando:

1
ls /sys/kernel/debug/usbmon

quello che avrete in risposta è una stringa come quella mostrata nello screenshoot che potete vedere qui sotto.

Schermata.png

E’ arrivato il momento di decidere se sniffare qualsiasi porta usb o concentrare le nostre attenzioni sul solo bus al quale magari è attaccata la chiavetta di memoria della quale ci interessa controllare il traffico.

Se volete ascoltare il traffico di tutte le porte sarà sufficiente dare il seguente comando:

1
cat /sys/kernel/debug/usbmon/0u > /tmp/1.mon.out

oppure procedere con l’individualizzazione della porta alla quale siamo interessati.

Per far ciò dovete digitare in una console il seguente comando:

1
cat /proc/bus/usb/devices

In questo modo avrete un listato completo di tutte le periferiche usb collegate al pc come nello screenshoot che segue:

Schermata2.png

potete quindi isolare la porta che più vi interessa analizzando l’output del comando ed identificando il venditore della periferica o altre informazioni che vi potranno portare diritti alla porta utilizzata.

Una volta individuato il gruppo di informazioni che descrive l’hardware da voi cercato potrete comodamente leggere il bus utilizzato alla prima stringa T dove troverete la dicitura Bus=02, esso corrisponderà in modo univoco all’autobus 2.

Ora potete iniziare la cattura con il comando:

1
cat /sys/kernel/debug/usbmon/2u > /tmp/1.mon.out

Personalmente preferisco questo secondo metodo visto che alcune periferiche ormai di uso comune come mouse usb o altro andrebbero ad inquinare le informazioni catturate con i solo segnali poco interessanti costringendoci di fatto a fare una successiva cernita dei risultati ottenuti per estrapolare solo i dati utili.

Ultimata la cattura delle informazione un bel ctrl+c riporterà la shell in condizioni normale e voi potrete dedicarvi all’analisi del file di dump che avete appena salvato con il nome di 1.mon.out.

Non sto ora qui a dilungarmi su come e cosa utilizzare per l’interpretazione dei dati raccolti ma sappiate che molte informazioni sensibili possono attraversare le porte usb lascio quindi a voi il piacere di scoprire le molteplici possibilità che questa tecnica offre.

Se siete di quelli che vedono complotti ai vostri danni in ogni angolo del globo vi consiglio di fare come i ragazzi di LolloBox (saluto con affetto ascii ci vediamo mercoledì sera) e di “murare vive” le porte usb con della sana colla a caldo.

Ciao a tutti.