rootでログインできなくなったのを復旧

 事の発端は、bashportsからインストールしようとしてmake installしたつもりがmakeしかしていなかったのに、気づかずにログインシェルを/usr/local/bin/bashに変更してしまったことだった。起動後パスワードを入れても/usr/local/bashが見つからないというエラーが出てログインプロンプトに戻ってしまうのだ。一般ユーザーのログインシェルも同時にbashにしていたため、まったくログインできなくなってしまった。
 さて、これを復旧するのにはじめはシングルユーザーモードで起動して/etc/passwdを書き換えようとしたのだが、リードオンリーモードでマウントされていたので書き換えできず。次にインストールCD/DVDのFixItモードを試してみた。
 まずはマウントするファイルシステムを探す。

Fixit# dmesg | grep ST
ad4: 305245MB  at ata2-master SATA150

これだけでは不十分で、どのパーティションかを探さなくてはならない。正確には「スライス」とスライスの中にある「パーティション」である。

Fixit# fdisk /dev/ad4
 ******* Working on device /dev/ad4 *******
parameters extracted from in-core disklabel are:
cylinders=620181 heads=16 sectors/track=63 (1008 blks/cyl)

Figures below won't work with BIOS for partitions not in cyl 1
parameters to be used for BIOS calculations are:
cylinders=620181 heads=16 sectors/track=63 (1008 blks/cyl)

Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
    start 63, size 625137282 (305242 Meg), flag 80 (active)
        beg: cyl 0/ head 1/ sector 1;
        end: cyl 1023/ head 254/ sector 63
The data for partition 2 is:

The data for partition 3 is:

The data for partition 4 is:

スライスは1番目、つまり/dev/ad4s1であることがわかった。
次にパーティション

Fixit# bsdlabel ad4s1
# /dev/ad4s1:
8 partitions:
#        size   offset    fstype   [fsize bsize bps/cpg]
  a: 616748674  8388608    4.2BSD     2048 16384 28528 
  b:  8388608        0      swap                    
  c: 625137282        0    unused        0     0         # "raw" part, don't edit

どうやらaというパーティションがルートのようだ。そこでこのパーティションを/mntにマウント。念のために書き込み可能なように指定しておこう。

Fixit# mount -o rw /dev/ad4s1a /mnt

いよいよハードディスクをいじる準備ができたので、パスワードファイルを編集する。

Fixit# vi /mnt/etc/passwd

はじめはこれでいけると思っていたのだが、知識不足だった。FreeBSDではパスワードファイルが/etc/passwdと/etc/master.passwdの二つがあり、/etc/passwdだけを変更しても無効なのだ。vipw -hと入力してみると

vipw: illegal option -- h
usage: vipw [-d directory]

こんな表示が出た。どうやらパスワードファイルが入っているディレクトリを指定できるみたいだな。

Fixit# vipw -d /mnt/etc/

これで一見うまくいったように見えたのだが、データベースがアップデートされておらずだめだった。なんだか疲れてきた…。
Fixitでググってみると、みんなFixitモードに入ったとたんchrootというコマンドを使っている。これを使うとルートディレクトリを偽装できるのだ。

Fixit# chroot /mnt
# vipw
vipw: pw_edit(): No such file or directory

あーもういらいらしてきた。環境変数EDITORが設定されていないとこのエラーが出るんだと。

# setenv EDITOR /usr/bin/vi
# vipw

これでパスワードファイル編集に入ったのだが、またもやデータベースのアップデートがなされていない模様。
 そろそろ別のアプローチを考えよう。ということで、ハードディスクから起動し、シングルユーザーモードに突入。そしてルートディレクトリを書き込み可能モードでマウントしなおす。

# mount -o rw /dev/ad4s1a /
# mount -l
/dev/ad4s1a on / (ufs, local, soft-updates)
devfs on /dev (devfs, local)

おお、いけたぜ。あとはこの状態でvipwすれば万事オッケーだ。
ああ疲れた。