web-dev-qa-db-ja.com

ファイル内の1ビットをフリップするにはどうすればよいですか?

btrfsが自分自身を癒すことができるという主張 をテストするために、意図的にファイルにダメージを与えたいと思います。この記事では、ファイルシステムを削除し、1ビットを「反転」して写真を損傷した後、再マウントすることについて説明しています。古いファイルシステムでは、これは破損するだけですが、btrfsで修正されるはずです。理論的にはこれは理にかなっていますが、実際にテストしたいと思います。

問題は、その記事でhowが説明していないことです。
ファイルシステムの非常に特定の部分の単一ビットを変更するにはどうすればよいですか?

また、これはmustがオフラインファイルシステムで実行されるため、btrfsが私の書き込みを意図的なものとして認識しないことも指摘する必要があります。

Edit:質問(および議論)ではbtrfsについて多くのことを話しますが、この種の実装にファイルシステムに依存しない方法があるかどうか知りたいです破損(異なるRAIDタイプ/コントローラー/などで比較できるようにするため)。

35
Oli

私は専門家ではありませんが、btrfs-progsパッケージには実際にこれを行うためのツールが含まれていますが、ソースからビルドする必要があるかもしれません。いずれにせよ、btrfs-progsをインストールまたはビルドしたら、btrfs開発者がファイルシステムをテストするために使用するbtrfs-corrupt-blockツールを使用できるはずです。

さて、私が言ったように、btrfsをいじる時間はあまりないので、このツールの正確な使用法はわかりません。しかし、それを使用すると、オフラインファイルシステムを破損できるはずです。これは、破損したファイルが読み取られたときに修正されます(使用する別のコピーがあるようにRAIDまたは何かをセットアップしたと仮定します)。

20
strugee

@Oli-こんにちは、私は実際にその記事を書いたジム・ソルターです。仮想マシンで作業していたので、物事が簡単になりました。私がやったことは、JPEGファイルから始めて、16進エディタでそれを開いた。私が使用したのはBlessで、これは単純なapt-get install blessでUbuntuにインストールできます。

BlessでJPEGを開いた後、ページを数回押し下げてJPEGの「肉」にうまく入り込み、約50バイト分のデータを強調表示して、テキストエディターにコピーアンドペーストしました(私のケース、gEdit)。これは私に何かを探してくれました。

ここで、VMの各アレイにJPEGを保存しました。アレイの背後のストレージは、一連の.qcow2ファイルでした。 JPEGを配列に保存したら、各配列に関連付けられた.qcow2ファイルをBlessにロードし、それらを検索できます-それらは非常に大きくなく、JPEGといくつかのメタデータにすぎません-その50バイトパターン強調表示してJPEGからコピーしました。出来上がり、私はブロックが破損しました!この時点で、Blessを使用してVMの仮想ディスクに保存されているJPEGの個々のバイトを手動で編集できました。そして、重要なことに、各アレイでまったく同じ方法で編集しました。

唯一の欠点は、記事でテストしたRAID5アレイの場合、ストライプ自体のパリティではなく、ストライプ内のデータの実際のコピーを編集することを確認する必要があったことです。それ以外の場合は空の配列であるため、ストライプのFOLLOWINGブロックにデータがなく、パリティブロックにはデータブロックから変更されていないデータが含まれます。データブロックではなくパリティブロックを誤って編集した場合、イメージは変更されていないように見えます。

最後の注意点-これを行うために仮想マシンを必要としない-ベアメタルで同じことを同じ方法で行うことができます。 Niceの小さな.qcow2ファイルではなくrawドライブ全体で作業する必要があり、ドライブを引き出して別のマシンに配置する必要があるため、お尻が痛くなるだけです。ライブ(または単なる代替)環境を起動して、それらを台無しにします。 (私はZFSのデータヒーリングをまさにこの方法でテストしましたが、実際のベアメタルマシンでは、7年ほど前に初めて次世代のファイルシステムに興味を持ちました。)

お役に立てれば!

16
Jim Salter
  1. 100万セクターオフセットのオフセットを使用して、ブロックデバイス上の単一セクターの値(例:/dev/sda1)を取得します(単なる例)。

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

    この任意に選択された1M * 512バイトのオフセットは、ファイルシステムのメタデータ部分から出て、実際にデータを含むセクターにいることを確認するためのものです。

  2. 16進エディターでコンテンツを変更して、未加工のセクターデータを編集します。たとえば、 Linuxに適した16進エディタが必要 を参照してください。

  3. if引数とof引数を逆にしてドライブのセクターを戻します。

    Sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    
16
gertvdijk

開いたファイルで FIBMAPioctl(2) を実行する小さなプログラムを試すことができます。

簡単なウェブ検索で、このブログ投稿を見つけました http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html これを行う方法の詳細-コンパイルして実行できるサンプルプログラムへのリンクも表示されます。

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

これは、hdparm --fibmap(@falconerによる言及)の実装方法とまったく同じです。

ブロック番号を見つけたら、dd gongfuを使用して、@ gertvdijkがスケッチしたようなファイルを変更できます。または、上記のfibmap.cプログラムを変更してビットフリップを行い、ファイルシステムレイヤーをバイパスしてデバイスファイルに直接書き込むこともできます(プログラムの3つのパラメーター:1.ファイルへのパス、2。ファイルシステムを含むデバイスファイル、3。修正したいオフセットとビット)。

免責事項:テストしていないため、FIBMAPioctl(2)がループバックデバイスまたはbtrfsファイルシステム内のファイルに対して機能することを保証できませんが、強く期待します私はguessingです。hdparmは、ファイルに対してioctl(2)を実行する前にデバイスタイプをチェックするため、失敗します。)

4
FooF
Sudo hdparm --fibmap /PATH/TO/FILE

ファイルが置かれているLBAを提供します。この後、@ gertvdijkの答えを使用できます。

3
falconer