LinuxにおけるgrubによるMBRの修復方法

LinuxにおけるMBRのまとめとバックアップ方法」で調べたとおりHDDの先頭セクタに置かれるMBRLinuxがブートするためには(Windowsでも)大変重要な512バイトになる。ここが壊れるとシステムがブートしなくなる。従って、LinuxにおけるMBRのまとめとバックアップ方法で考察したような方法でMBRをバックアップしておくことが必須と考える。*1

MBRには大きく分けてブートストラップローダの部分とパーティションテーブルの部分に分けられるが、パーティションテーブルの情報が失われるとHDDの何処にどのようなシステムが保存されているが分からなくなるので、基本的にはそのHDDにあるシステムを救うのは難しくなる。(シェルスクリプトパーティションテーブル復旧用のプログラムを組んでみたが、HDD全体をなめる必要があるので気の長くなるような時間がかかる。その内、Cで組んでみたいととは思っているが。)そのためMBRのバックアップは必須になるが、一方でブートストラップローダの部分は再インストールが可能である。パーティションテーブルさえ生き残っていればシステムを救うことは比較的簡単かと思う。そこで、その方法をメモしておく。なお、ここではGRUBをブートストラップローダとして検証している。(LILOWindowsの環境でのf復旧方法ではないのでアシカラズ。)

ちなみにMBRが壊れる原因はいくつか考えられるが、次のようなケースだろう。

  1. オペレーションミスによる破壊。
  2. 異なるOSをインストールすることによるMBRの上書き。
  3. ウィルスなどによる恣意的な破壊。(例えば「MBR感染機能付きルートキット「StealthMBR」」)

さて、まず実験の犠牲となるシステムを1つ選んで、次のようにしてMBRのブートストラップ部分をわざと壊しておく。(下手をするパーティションテーブルまで破壊するので、実験する際は注意すること。MBRのバックアップをとってから行う方がいい。バックアップは「MBRのバックアップ」を参照。)

 [root@fedora-8 ~]# hexdump -C -n 512 /dev/sda		: ←一応、内容を確認
 00000000  eb 48 90 10 8e d0 bc 00  b0 b8 00 00 8e d8 8e c0  |.H..............|
 00000010  fb be 00 7c bf 00 06 b9  00 02 f3 a4 ea 21 06 00  |...|.........!..|
 00000020  00 be be 07 38 04 75 0b  83 c6 10 81 fe fe 07 75  |....8.u........u|
 00000030  f3 eb 16 b4 02 b0 01 bb  00 7c b2 80 8a 74 03 02  |.........|...t..|
 00000040  80 00 00 80 41 20 01 00  00 08 fa 90 90 f6 c2 80  |....A ..........|
 00000050  75 02 b2 80 ea 59 7c 00  00 31 c0 8e d8 8e d0 bc  |u....Y|..1......|
 00000060  00 20 fb a0 40 7c 3c ff  74 02 88 c2 52 be 7f 7d  |. ..@|<.t...R..}|
 00000070  e8 34 01 f6 c2 80 74 54  b4 41 bb aa 55 cd 13 5a  |.4....tT.A..U..Z|
 00000080  52 72 49 81 fb 55 aa 75  43 a0 41 7c 84 c0 75 05  |RrI..U.uC.A|..u.|
 00000090  83 e1 01 74 37 66 8b 4c  10 be 05 7c c6 44 ff 01  |...t7f.L...|.D..|
 000000a0  66 8b 1e 44 7c c7 04 10  00 c7 44 02 01 00 66 89  |f..D|.....D...f.|
 000000b0  5c 08 c7 44 06 00 70 66  31 c0 89 44 04 66 89 44  |\..D..pf1..D.f.D|
 000000c0  0c b4 42 cd 13 72 05 bb  00 70 eb 7d b4 08 cd 13  |..B..r...p.}....|
 000000d0  73 0a f6 c2 80 0f 84 ea  00 e9 8d 00 be 05 7c c6  |s.............|.|
 000000e0  44 ff 00 66 31 c0 88 f0  40 66 89 44 04 31 d2 88  |D..f1...@f.D.1..|
 000000f0  ca c1 e2 02 88 e8 88 f4  40 89 44 08 31 c0 88 d0  |........@.D.1...|
 00000100  c0 e8 02 66 89 04 66 a1  44 7c 66 31 d2 66 f7 34  |...f..f.D|f1.f.4|
 00000110  88 54 0a 66 31 d2 66 f7  74 04 88 54 0b 89 44 0c  |.T.f1.f.t..T..D.|
 00000120  3b 44 08 7d 3c 8a 54 0d  c0 e2 06 8a 4c 0a fe c1  |;D.}<.T.....L...|
 00000130  08 d1 8a 6c 0c 5a 8a 74  0b bb 00 70 8e c3 31 db  |...l.Z.t...p..1.|
 00000140  b8 01 02 cd 13 72 2a 8c  c3 8e 06 48 7c 60 1e b9  |.....r*....H|`..|
 00000150  00 01 8e db 31 f6 31 ff  fc f3 a5 1f 61 ff 26 42  |....1.1.....a.&B|
 00000160  7c be 85 7d e8 40 00 eb  0e be 8a 7d e8 38 00 eb  ||..}.@.....}.8..|
 00000170  06 be 94 7d e8 30 00 be  99 7d e8 2a 00 eb fe 47  |...}.0...}.*...G|
 00000180  52 55 42 20 00 47 65 6f  6d 00 48 61 72 64 20 44  |RUB .Geom.Hard D|
 00000190  69 73 6b 00 52 65 61 64  00 20 45 72 72 6f 72 00  |isk.Read. Error.|
 000001a0  bb 01 00 b4 0e cd 10 ac  3c 00 75 f4 c3 00 00 00  |........<.u.....|
 000001b0  00 00 00 00 00 00 00 00  f2 e3 02 00 00 00 80 01  |................|
 000001c0  01 00 83 fe 3f 18 3f 00  00 00 9a 20 06 00 00 00  |....?.?.... ....|
 000001d0  01 19 8e fe ff ff d9 20  06 00 3b ca f9 00 00 00  |....... ..;.....|
 000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
 00000200
 [root@fedora-8 ~]# dd if=/dev/zero bs=1 count=446 of=/dev/sda	: ←ローダ部分を破壊
 446+0 records in
 446+0 records out
 446 bytes (446 B) copied, 0.000633598 s, 704 kB/s
 [root@fedora-8 ~]# hexdump -C -n 512 /dev/sda		: ←壊れていることを確認
 00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 *
 000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 80 01  |................|
 000001c0  01 00 83 fe 3f 18 3f 00  00 00 9a 20 06 00 00 00  |....?.?.... ....|
 000001d0  01 19 8e fe ff ff d9 20  06 00 3b ca f9 00 00 00  |....... ..;.....|
 000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
 00000200
 [root@fedora-8 ~]# 

これでパーティションテーブルの手前まで全てゼロで潰した。この状態でリブートすると、当然システムは立ち上がらない。(赤い部分は後で解説。)

grub-installによるMBRの簡易修復

まず、CD/DVDからブートしてCD/DVDとメモリだけで動作するISO Linuxを起動する。ディストリビューションにより多少の違いはあるが、基本的には殆どのディストリビューションで提供している筈。ここではFedora 8のインストールDVDをレスキューモードで起動してシェルの状態にする。(UbuntuであればインストールDVDから“コンピュータに変更を加えないでUbuntuをつかてみる”を選択して起動すればウィンドウ環境のISO Linuxが動くので便利。Fedoraでのレスキューモードでの立ち上げ方は「ふろく:レスキューモードの起動手順」を参照。ここではFedoraを使って検証したが、シェルさえ使えればUbuntuでも他のディストリビューションでも大差はないと思う。)

レスキューモードで立ち上がったら grub-install というコマンドを使う。レスキューモードで問題なく立ち上がっていればHDDに入っているルートファイルシステムは“/mnt/sysimage/”というディレクトリにマウントされ、/bootのファイルシステム(がもしあれば)“/mnt/sysimage/boot/”というディレクトリのマウントされているはずである。つまり“/mnt/sysimage/”がHDDにインストールされている事実上の/(ルート)ディレクトリとなる。そこでまず、chrootコマンドでISO Linuxの環境からHDDのシステムの環境に移行する。

sh-3.2# chroot /mnt/sysimage/
sh-3.2#

chrootコマンドは何のメッセージも出さないので本当にルートディレクトリが変わっているか確認するには、/をlsしてみる。

sh-3.2# ls /
bin   dev  halt  lib    lost+found  mnt  proc  sbin     srv  tmp  var
boot  etc  home  lib64  media       opt  root  selinux  sys  usr
sh-3.2#

例えば、/homeはISO Linuxには無いので、これがあればchrootできていることが確認できる。
そして次にgrub-installを実行する。

sh-3.2# grub-install /dev/sda
Installation finished. No error reported.
This is the contents of the device map /boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

# this device map was generated by anaconda
(hd0)     /dev/sda
sh-3.2#


これでsdaディスクのMBRが修復できた。確認のためMBRのダンプをとってみる。

 sh-3.2# hexdump -C -n 512 /dev/sda
 00000000  eb 48 90 00 00 00 00 00  00 00 00 00 00 00 00 00  |.H..............|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 *
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 03 02  |................|
 00000040  ff 00 00 20 01 00 00 00  00 02 fa 90 90 f6 c2 80  |... ............|
 00000050  75 02 b2 80 ea 59 7c 00  00 31 c0 8e d8 8e d0 bc  |u....Y|..1......|
 00000060  00 20 fb a0 40 7c 3c ff  74 02 88 c2 52 be 7f 7d  |. ..@|<.t...R..}|
 00000070  e8 34 01 f6 c2 80 74 54  b4 41 bb aa 55 cd 13 5a  |.4....tT.A..U..Z|
 00000080  52 72 49 81 fb 55 aa 75  43 a0 41 7c 84 c0 75 05  |RrI..U.uC.A|..u.|
 00000090  83 e1 01 74 37 66 8b 4c  10 be 05 7c c6 44 ff 01  |...t7f.L...|.D..|
 000000a0  66 8b 1e 44 7c c7 04 10  00 c7 44 02 01 00 66 89  |f..D|.....D...f.|
 000000b0  5c 08 c7 44 06 00 70 66  31 c0 89 44 04 66 89 44  |\..D..pf1..D.f.D|
 000000c0  0c b4 42 cd 13 72 05 bb  00 70 eb 7d b4 08 cd 13  |..B..r...p.}....|
 000000d0  73 0a f6 c2 80 0f 84 ea  00 e9 8d 00 be 05 7c c6  |s.............|.|
 000000e0  44 ff 00 66 31 c0 88 f0  40 66 89 44 04 31 d2 88  |D..f1...@f.D.1..|
 000000f0  ca c1 e2 02 88 e8 88 f4  40 89 44 08 31 c0 88 d0  |........@.D.1...|
 00000100  c0 e8 02 66 89 04 66 a1  44 7c 66 31 d2 66 f7 34  |...f..f.D|f1.f.4|
 00000110  88 54 0a 66 31 d2 66 f7  74 04 88 54 0b 89 44 0c  |.T.f1.f.t..T..D.|
 00000120  3b 44 08 7d 3c 8a 54 0d  c0 e2 06 8a 4c 0a fe c1  |;D.}<.T.....L...|
 00000130  08 d1 8a 6c 0c 5a 8a 74  0b bb 00 70 8e c3 31 db  |...l.Z.t...p..1.|
 00000140  b8 01 02 cd 13 72 2a 8c  c3 8e 06 48 7c 60 1e b9  |.....r*....H|`..|
 00000150  00 01 8e db 31 f6 31 ff  fc f3 a5 1f 61 ff 26 42  |....1.1.....a.&B|
 00000160  7c be 85 7d e8 40 00 eb  0e be 8a 7d e8 38 00 eb  ||..}.@.....}.8..|
 00000170  06 be 94 7d e8 30 00 be  99 7d e8 2a 00 eb fe 47  |...}.0...}.*...G|
 00000180  52 55 42 20 00 47 65 6f  6d 00 48 61 72 64 20 44  |RUB .Geom.Hard D|
 00000190  69 73 6b 00 52 65 61 64  00 20 45 72 72 6f 72 00  |isk.Read. Error.|
 000001a0  bb 01 00 b4 0e cd 10 ac  3c 00 75 f4 c3 00 00 00  |........<.u.....|
 000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 80 01  |................|
 000001c0  01 00 83 fe 3f 18 3f 00  00 00 9a 20 06 00 00 00  |....?.?.... ....|
 000001d0  01 19 8e fe ff ff d9 20  06 00 3b ca f9 00 00 00  |....... ..;.....|
 000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
 00000200
 sh-3.2#

あとはrebootコマンドでリブートすれば無事に立ち上がる。

確かに立ち上がるのだけども、MBR(=第0セクタ)のダンプの内容を確認するとなんか変だ。もともとのブートストラップローダ(1次ローダ)では2次ローダをHDDの 0x00012041セクタから読むが、grub-installでインストールした1次ローダは2次ローダをHDDの 0x00000001セクタ(つまり第1セクタ)から読むようになっている。

そこで第1セクタをダンプしてみると確かに2次ローダらしい情報が書き込まれている。色々しらべたら第1セクタ〜第24セクタまでext2/ext3用の1.5次ローダ(/boot/grub/e2fs_stage1_5をちょっと修正したもの)が書き込まれている。

つまり、grub-installでインストールした1次ローダはいきなり2次ローダを読み込むのではなく、ファイルシステムに合わせた1.5次ローダを読み込む形なっていた。

まぁ、無事にブートできるようになったのだから、良いのは良いのだが。

ここで、ちょっと実験をした。最初のMBRのバックアップを元に戻してみた。そしたらブートしない。GRUBがハングアップしたり暴走したりする。つまり、grub-installによって2次ローダに変更が加えられて、HDD上の位置が変ってしまったために立ち上がらなくなってしまった、と推測できる。

まとめるとgrub-installによるMBRの簡易修復の留意点は以下のようになる。

  • MBRのバックアップを取ってある場合は、ISO Linuxを立ち上げて直ぐにバックアップをリストアして修復を試みる。(リストア方法は「MBRのバックアップ 」参照)
  • もし、バックアップが無い、もしくはバックアップをリストアしても元通りにならなかったら、gub-installでMBRを修復する。
  • だたし、grub-installを使うとstage2にも変更が加えられるので、その後に以前のMBRのバックアップをリストアしてはいけない。システムは立ち上がらなくなる。(その場合は、再度、grub-installを実行する。)

grubによるMBRの修復

/sbin/grub-installはシェルスクリプトで書かれたコマンドでgrubプリプロセッサとなっている。grubは機能は高いが使いこなすにはある程度の知識が必要になるので、予めgrub-installでgrubへ渡すパラメータを用意した上でgrubを呼び出して使う形となる。逆に言えば、grub-installでは“お任せ”になってしまうので、きめの細かい設定ができない。

ブートストラップローダから直接2次ローダを呼び出すようにするためにはgrubを使わないとならないようだ。(grub-installの隠しオプションの含めて眺めてみたが、grub-installからは無理の様だ。)

そこで、grubの出番となるが、grubは機能が高く奥深いので調べ始めるとキリがない。ここではブートストラップローダから直接2次ローダを呼び出すように設定するところに限定して例を載せておく。

ISO Linuxが起動した時点でgrubを実行し、次のgrubコマンドを与える。(chrootする必要はない。)

sh-3.2# grub
grub> root (hd0,0)
grub> install /grub/stage1 d (hd0) /grub/stage2 p (hd0,0)/grub/grub.conf
grub> quit
sh-3.2#

“root (hd0,0)”はGRUGがインストールされているファイルシステム(つまり /bootのファイルシステム)のパーティションを指定している。この例では最初のHDDの最初のパーティションが/bootファイルシステムになっている(Fedoraのデフォルトの設定)。この指定をすれば次のinstallコマンドの引数で一々パーティションを指定する必要はなくなる。(逆にrootコマンドを実行しないでinstallの引数で一々指定してもインストールできる。)
installコマンドの引数は

  • 1次ローダの指定
  • 1次ローダのあるデバイスの指定オプション“d”:指定しないとMBRの0x40番地は“0xff”となり、BIOSから与えられたデバイスを使う。指定する場合はrootコマンドで指定されたデバイスとなり、通常は“0x80”が書き込まれる。
  • 1次ローダをインストールするHDD ”(hd0)”
  • 2次ローダの指定
  • 2次ローダの修飾の指定オプション “p”:この“p”を指定すると2次ローダの0x208〜0x20B番地の“install_partition”を設定しなおす。
  • grub.confの指定。この文字列が2次ローダ内部に書き込まれるのでパーティションの指定が必要。この文字列が2次ローダの0x217番地以降に埋め込まれる。

となる。rootコマンドでGRUBファイルシステムを指定されていない場合は、次の様に引数を指定する。

grub> install (hd0,0)/grub/stage1 d (hd0) (hd0,0)/grub/stage2 p (hd0,0)/grub/grub.conf


さて、この結果のMBRは以下の通り。

 sh-3.2# hexdump -C -n 512 /dev/sda
 00000000  eb 48 90 00 00 00 00 00  00 00 00 00 00 00 00 00  |.H..............|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 *
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 03 02  |................|
 00000040  80 00 00 80 6f 28 01 00  00 08 fa 90 90 f6 c2 80  |....o(..........|
 00000050  75 02 b2 80 ea 59 7c 00  00 31 c0 8e d8 8e d0 bc  |u....Y|..1......|
 00000060  00 20 fb a0 40 7c 3c ff  74 02 88 c2 52 be 7f 7d  |. ..@|<.t...R..}|
 00000070  e8 34 01 f6 c2 80 74 54  b4 41 bb aa 55 cd 13 5a  |.4....tT.A..U..Z|
 00000080  52 72 49 81 fb 55 aa 75  43 a0 41 7c 84 c0 75 05  |RrI..U.uC.A|..u.|
 00000090  83 e1 01 74 37 66 8b 4c  10 be 05 7c c6 44 ff 01  |...t7f.L...|.D..|
 000000a0  66 8b 1e 44 7c c7 04 10  00 c7 44 02 01 00 66 89  |f..D|.....D...f.|
 000000b0  5c 08 c7 44 06 00 70 66  31 c0 89 44 04 66 89 44  |\..D..pf1..D.f.D|
 000000c0  0c b4 42 cd 13 72 05 bb  00 70 eb 7d b4 08 cd 13  |..B..r...p.}....|
 000000d0  73 0a f6 c2 80 0f 84 ea  00 e9 8d 00 be 05 7c c6  |s.............|.|
 000000e0  44 ff 00 66 31 c0 88 f0  40 66 89 44 04 31 d2 88  |D..f1...@f.D.1..|
 000000f0  ca c1 e2 02 88 e8 88 f4  40 89 44 08 31 c0 88 d0  |........@.D.1...|
 00000100  c0 e8 02 66 89 04 66 a1  44 7c 66 31 d2 66 f7 34  |...f..f.D|f1.f.4|
 00000110  88 54 0a 66 31 d2 66 f7  74 04 88 54 0b 89 44 0c  |.T.f1.f.t..T..D.|
 00000120  3b 44 08 7d 3c 8a 54 0d  c0 e2 06 8a 4c 0a fe c1  |;D.}<.T.....L...|
 00000130  08 d1 8a 6c 0c 5a 8a 74  0b bb 00 70 8e c3 31 db  |...l.Z.t...p..1.|
 00000140  b8 01 02 cd 13 72 2a 8c  c3 8e 06 48 7c 60 1e b9  |.....r*....H|`..|
 00000150  00 01 8e db 31 f6 31 ff  fc f3 a5 1f 61 ff 26 42  |....1.1.....a.&B|
 00000160  7c be 85 7d e8 40 00 eb  0e be 8a 7d e8 38 00 eb  ||..}.@.....}.8..|
 00000170  06 be 94 7d e8 30 00 be  99 7d e8 2a 00 eb fe 47  |...}.0...}.*...G|
 00000180  52 55 42 20 00 47 65 6f  6d 00 48 61 72 64 20 44  |RUB .Geom.Hard D|
 00000190  69 73 6b 00 52 65 61 64  00 20 45 72 72 6f 72 00  |isk.Read. Error.|
 000001a0  bb 01 00 b4 0e cd 10 ac  3c 00 75 f4 c3 00 00 00  |........<.u.....|
 000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 80 01  |................|
 000001c0  01 00 83 fe 3f 18 3f 00  00 00 9a 20 06 00 00 00  |....?.?.... ....|
 000001d0  01 19 8e fe ff ff d9 20  06 00 3b ca f9 00 00 00  |....... ..;.....|
 000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
 00000200  

あとはリブートすれば通常通り起動する。

この方法であれば、Linuxを最初にインストールした時と同様、1次ローダから直接2次ローダを起動するための第1セクタ〜第62セクタは使われない。

なお、grubブートローダを設定する場合は、installコマンドではなくsetupコマンドを使うのが一般的のようだ。しかし、setupコマンドでは1.5次ローダを見つけると自動的に1.5次ローダをインストールしてしまう。そのため、1.5次ローダを使いたくない場合は直接 installコマンドを使う必要があるようだ。(ただし、setupコマンドで1.5次ローダが見つからないように1.5次ローダのファイルを予め別のディレクトリへ移動しておくと(つまり隠しておくと)、直接2次ローダを呼び出す構成でインストールする。)

*1:今後はMBR方式からEFI方式へ移行すると思うので、今後は余り使うことがなくなるかも知れないが、一応調べて理解しておくことは意味があるかなと思う。EFIに関しての管理に関してはその内、機会があれば調べてみたい。

ふろく:レスキューモードの起動手順

Fedora-8のインストールDVD

  • メニューから“Rescue installed system”を選択


  • 言語を選択”Japanese”


  • しかし日本語使えないというメッセージが出る


  • キーボードの選択。日本語キーボードであれば“jp106”


  • ネットワークを使うかどうか。修復作業中に使わないのであれば“No”


  • HDDの内容をマウントするかどうか。お任せマウントするのであれば“Continue”


パーティションテーブルが壊れていればマウントできない)

  • 無事にマウントできたメッセージ。環境を変えるときはchrootを使ってね、との説明


  • 以上で設定は終了。レスキューモードでシェルが使えるようになる