Come posso capovolgere un singolo bit in un file?


35

Voglio danneggiare intenzionalmente un file per testare le affermazioni secondo cui btrfs può guarire se stesso . L'articolo parla di come togliere il filesystem, danneggiare una foto "capovolgendola" un po 'e poi rimontandola. Nei filesystem più vecchi questo sarebbe semplicemente corrotto ma dovrebbe risolversi in btrfs. In teoria, questo ha senso, ma voglio davvero provarlo.

Il problema è che l'articolo non spiega come farlo.
Come potrei cambiare un singolo bit in una parte molto specifica di un filesystem?

Dovrei anche sottolineare che questo deve essere fatto su un filesystem offline in modo che btrfs non consideri la mia scrittura intenzionale.

Modifica: Mentre la domanda (e la discussione) parla molto di btrfs, mi piacerebbe sapere se ci sono metodi indipendenti dal filesystem per implementare questo tipo di corruzione (in modo che possa essere confrontato tra diversi tipi di RAID / controller / etc).


@Dan Voglio dire che se modifico direttamente il file, btrfs (o qualsiasi altro filesystem in quel caso) lo considererebbe una scrittura valida. Non darebbe la corruzione che sto cercando.
Oli

Si tratta di un filesystem di prova (vale a dire, non ti interessa il contenuto o stai perfettamente bene con il ripristino dal backup? Inoltre, stai usando una singola partizione btrfs su una singola unità o una singola partizione sopra un array RAID o qualche altra configurazione?
Darth Android

1
Se btrfs supporta gli ioctls giusti (non sono sicuro che lo faccia), è possibile utilizzare filefrag -vper scoprire esattamente dove si trova un file.
derobert,

3
@Oli Sospetto che troverai un pubblico più interessato a U&L, sia in termini di voti sia in termini di risposte. inoltre questo .
Strugee,

1
Spara un raggio cosmico nel punto giusto.
smcg

Risposte:


20

Non sono un esperto, ma il btrfs-progspacchetto in realtà include uno strumento specifico per farlo, anche se potrebbe essere necessario compilare dal sorgente. In ogni caso, una volta installato o creato btrfs-progs, dovresti essere in grado di utilizzare lo strumento btrfs-corrupt-block, che viene utilizzato dagli sviluppatori di btrfs per testare il filesystem.

Ora, come ho detto, non ho avuto molto tempo per giocare con btrfs, quindi non conosco l'uso esatto di questo strumento. Ma con esso, dovresti essere in grado di corrompere un filesystem offline, che verrà risolto quando il file corrotto viene letto (supponendo che tu abbia impostato RAID o qualcosa in modo che ci sia un'altra copia da usare).


2
Fantastica scoperta! Supponendo che in btrfs-corrupt-blockrealtà sia stato scritto per essere un vero test e non un "trucco" da parte degli sviluppatori di btrfs, questo dovrebbe adattarsi esattamente al conto.
allquixotic

@allquixotic se vuoi saperne di più su btrfs, c'è una bella chiacchierata da linux.conf.au 2012 . come ho detto, btrfs-corrupt-blockviene utilizzato dagli sviluppatori, quindi non sarebbe molto utile se fosse un trucco :)
strugee,

3
@allquixotic Questa è la bellezza dell'open source: puoi guardare il codice sorgente di btrfs e controllarlo! Certo, questo non sarà un compito facile, ma se lo vuoi davvero, puoi farlo.
Bakuriu,

@Bakuriu Ne sono perfettamente consapevole. Non ho mai dubitato seriamente che btrfs-corrupt-blocknon sia un test sincero, poiché sarebbe stato scoperto molto rapidamente da qualcuno che cercava la fonte e usato come PR negativo contro Oracle (almeno; così come qualsiasi altro sviluppatore / collaboratore di btrfs). Era solo un commento fuori dal comune.
allquixotic,

Mi chiedo se l'OP (@Oli) voglia corrompere un blocco (cioè la struttura del filesystem) o un file (cioè il contenuto di un file ??) ... E credo che l'affermazione di btrfs di auto-guarigione riguardi il primo, non il secondo? [come fa un filesystem a sapere quale bit è stato capovolto in un file? qualche tipo di CRC?]. Questa risposta è probabilmente a destra, tuttavia, quindi +1. [ma può cambiare più di un "singolo bit"? o cambiare qualcosa che può essere guarito più facilmente di un po 'casuale che accade "ovunque"?]
Olivier Dulac,

16
  1. Ottieni il valore di un singolo settore sul dispositivo a blocchi (ad es. /dev/sda1) Con un offset di 1 milione di settori (solo un esempio):

    sudo dd if=/dev/sda1 of=/root/mysector bs=512 count=1 skip=1M
    

    Questo offset arbitrario da 1 M * 512 byte scelto è solo per assicurarsi di essere fuori dalla parte dei metadati del filesystem e in realtà su un settore che contiene dati.

  2. Modifica i dati del settore non elaborato modificando il contenuto con un editor esadecimale. Vedi ad esempio Hai bisogno di un buon editor esadecimale per Linux .

  3. Rimetti il ​​settore sul disco con gli argomenti ife ofinvertiti:

    sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    

2
Questo non lo aiuterà a testare a meno che il milionesimo blocco non sia effettivamente parte di un file. Come può cercare su quale blocco inizia un determinato file?
Darth Android

3
È così quasi lì. Se riesci a bloccare il comando dd sulla posizione esatta del file, questo è probabilmente il modo migliore per affrontarlo.
Oli

@Oli Sì, so come farlo per la famiglia di file system Ext, ma non ho molta esperienza con btrfs. Fammi vedere se riesco a trovare un modo.
gertvdijk,

2
@Oli: puoi semplicemente avere un loop, dd che espelle blocco per blocco (cioè, come sopra, ma "skip = N", N essendo in 1..max) fino a quando non puoi estrarre una linea dal file che desideri modificare [provare a generare una linea che non accadrà da nessun'altra parte, ad esempio prenderla da un generatore di password e abbastanza a lungo?]. Quindi modifichi quel particolare blocco. rimonta, verifica se la modifica è stata ripristinata (che dubito, vedi il mio commento nella risposta in alto ... sembra esserci una confusione tra i dati dei file (= contenuto) e la struttura del filesystem stesso (= come sono organizzati i file e il loro contenuto )?)
Olivier Dulac il

16

@Oli - ciao, sono Jim Salter, il ragazzo che ha effettivamente scritto quell'articolo. Stavo lavorando con una macchina virtuale, il che ha reso le cose più semplici. Quello che ho fatto è iniziato con un file JPEG e l'ho aperto in un editor esadecimale. Quello particolare che ho usato era Bless, che puoi installare in Ubuntu con un semplice apt-get install bless .

Dopo aver aperto il file JPEG in Bless, ho premuto alcune volte la pagina per approfondire la "carne" del file JPEG, quindi ho semplicemente evidenziato i dati per una cinquantina di byte e li ho copiati e incollati in un editor di testo (nel mio case, gEdit). Questo mi ha dato qualcosa da cercare.

Ora ho salvato il JPEG in ciascun array sulla VM. La memoria dietro gli array era una serie di file .qcow2. Una volta salvato il JPEG negli array, ho potuto caricare i file .qcow2 associati a ciascun array in Bless e cercarli - non erano molto grandi, essendo nient'altro che il JPEG e alcuni metadati - per quel modello di cinquanta byte Avevo evidenziato e copiato dal JPEG. Voila, ho avuto il blocco da corrompere! A questo punto, potrei semplicemente modificare manualmente i singoli byte del JPEG come memorizzati sul disco virtuale della VM usando Bless - e, cosa più importante, farlo esattamente allo stesso modo su ciascun array.

L'unica ruga è che nel caso dell'array RAID5 testato nell'articolo, ho dovuto assicurarmi di aver modificato la copia effettiva dei dati nella striscia e non la parità per la striscia stessa: era una piccola immagine su un altrimenti array vuoto, quindi non c'erano dati nel blocco FOLLOWING nella striscia, rendendo il blocco di parità contenente i dati inalterati dal blocco di dati. Se avessi modificato accidentalmente il blocco di parità anziché il blocco di dati, l'immagine sarebbe stata visualizzata come invariata.

Un'ultima nota - non hai BISOGNO di macchine virtuali per farlo - potresti fare le stesse cose allo stesso modo con il bare metal; sarebbe solo più una seccatura nel culo perché avresti bisogno di lavorare con intere unità raw anziché con piccoli file .qcow2 piccoli e dovresti o estrarre le unità e metterle in una macchina diversa, oppure avviare in un ambiente live (o semplicemente alternativo) per scherzare con loro. (Ho testato la guarigione dei dati di ZFS esattamente in questo modo, ma su macchine bare metal reali, 7 anni fa, quando mi sono interessato per la prima volta ai filesystem di nuova generazione.)

Spero che sia di aiuto!


4

È possibile provare un piccolo programma che verrà eseguito sul file aperto.FIBMAP ioctl(2)

Tramite una rapida ricerca sul Web, ho trovato questo post sul blog http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html che spiega in dettaglio come fare: ti fornirà persino un link in un programma di esempio che puoi compilare ed eseguire da solo.

$ git clone git://kernel.ubuntu.com/cking/debug-code
$ cd debug-code/block-mapper-fibmap
$ make
$ sudo ./fibmap /path/to/your/image-file.jpg

Questo è esattamente il modo in hdparm --fibmapcui (citato da @falconer) è implementato.

Dopo aver trovato i numeri di blocco è possibile utilizzare ddgongfu per modificare il file, come lo schizzo di @gertvdijk. O forse potresti semplicemente modificare il fibmap.cprogramma sopra per fare il capovolgimento dei bit per te, scrivendo direttamente nel file del dispositivo bypassando il livello del file system (tre parametri per il programma: 1. il percorso del file, 2. file del dispositivo contenente il file sistema, 3. offset e bit che si desidera modificare).

( Disclaimer: non ho ancora testato e non può garantire che il FIBMAP ioctl(2)funzionerà per un file in un dispositivo di loopback o btrfs file system, ma vorrei fortemente aspetterebbe che fa sto. Indovinando hdparm controllerà il tipo di dispositivo prima di eseguire il ioctl(2)sul file ed è, quindi, fallendo.)


3
sudo hdparm --fibmap /PATH/TO/FILE

ti darà gli LBA in cui si trova il file. Dopodiché puoi usare la risposta di @gertvdijk.


Sfortunatamente questo non sembra funzionare. Sta sputando a 0,39: device not found in /devÈ o perché è btrfs o (più probabilmente) perché lo sto usando su file tenuti in loopback. Proverò a farlo con una VM "corretta".
Oli

@Oli Hmm. Ho pensato che hdparmfunzionasse su ogni file system ma forse non è così.
falconiere
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.