システムのパーミッションを大幅に狂わせてしまった時

事故が起こるのは常に一瞬であり、一方平穏を取りもどすのはとても難しい

後輩が公開Subversionリポジトリを研究室のサーバに作っていたが、聞けば/root/SVNに作ったという。いやいや、/rootは700でしょうと俺は諭して議論の結果/var/svnとかが適切だけども容量の関係で他の場所に移動することになった。さて、問題は/rootのパーミッションを元に戻さねばならない。簡単、朝飯前である。

/root# chmod -R go-rwx *
ls -la /root

いかん、隠しファイルどもが残ってしまった。やり直し、やり直し。

/root# chmod -R go-rwx .*

これにて一件落着…にしては終わるのが遅すぎる。そして、permission deniedとか言っている。いや、そんなややこしい話じゃないんじゃ?そして、そのログを見てみると/proc/なんちゃらとか書いてあった。

修復が簡単そうに見えたとしても実際の手間はその何倍にもなる

うわー、やってもたわー、と言う感じである。つまり、.*と書いてしまうと、..が入ってしまってルートから全部chmodしてしまうことになったわけである。ちなみにもしZshを使っていたら.*と入力したところで<Tab>を入力するとグロブパターンがその場で展開されるのでこういう時も「あれ、..が入っている」とか気付けるので安心である。rootでZshとか見たことないけどな。なにはともあれ急いでC-cで止めて現状確認を行う。

#ls -l /
合計 84
drwx------   2 root root  4096 2012-xx-xx 11:47 bin/
drwx------   4 root root  4096 2012-xx-xx 19:00 boot/
drwxr-xr-x  18 root root  3340 2013-xx-xx 17:52 dev/
drwxr-xr-x  92 root root  4096 2013-xx-xx 18:06 etc/
drwx------  22 root root  4096 2012-xx-xx 11:03 home/
lrwxrwxrwx   1 root root    30 2012-xx-xx 16:50 initrd.img -> boot/initrd.img-2.6.32-5-amd64
drwx------  11 root root 12288 2012-xx-xx 18:59 lib/
lrwxrwxrwx   1 root root     4 2012-xx-xx 16:41 lib64 -> /lib/
drwx------   2 root root 16384 2012-xx-xx 16:39 lost+found/
drwx------   3 root root  4096 2012-xx-xx 16:40 media/
drwx------   3 root root  4096 2012-xx-xx 16:34 mnt/
drwx------   4 root root  4096 2013-xx-xx 17:16 opt/
dr-x------ 139 root root     0 2013-xx-xx 17:51 proc/
drwx------   7 root root  4096 2013-xx-xx 18:20 root/
drwx------   2 root root  4096 2012-xx-xx 19:00 sbin/
drwx------   2 root root  4096 2010-xx-xx 15:30 selinux/
drwxr-xr-x   2 root root  4096 2012-xx-xx 16:41 srv/
drwxr-xr-x  13 root root     0 2013-xx-xx 17:51 sys/
drwxrwxrwt   5 root root  4096 2013-xx-xx 19:20 tmp/
drwx------  10 root root  4096 2012-xx-xx 16:41 usr/
drwxr-xr-x  16 root root  4096 2012-xx-xx 15:52 var/
lrwxrwxrwx   1 root root    27 2012-xx-xx 16:50 vmlinuz -> boot/vmlinuz-2.6.32-5-amd64

清々しいまでに700になっている。ただし、いくつか幸いなことがあった。

  • chmod 700とかではなくgoからrwxを消しただけなのでsuid,gid,stickyという一番厄介でイレギュラーなビットは全て保存されている。*1
  • これまた厄介な/etcと/varは手付かずだった。*2

というわけでまずは二次災害を防ぐために深呼吸三回してから作業にとりかかる。具体的には簡単なディレクトリでは次のようにして済ませた。

find /opt/hoge/ -perm u=rw  -exec chmod go+r  {} +
find /opt/hoge/ -perm u=rwx -exec chmod go+rx {} +

大体のファイルは644か755になっている訳で、だいたいこれでうまく行く。ただし、

  • 一部のファイルでは600や700が要求されることがある。
  • suid,sgid,stickyが付いていると-permの条件を満たさないのでこれで変更されない。

ことには留意されたい。なんにせよ、単純な場所以外でこういうことをして傷口を広げるのはおすすめできないので一度-printして自分のマシンと見比べるなどするのがいい。
/proc以下に関しては所詮カーネルの見せる幻影であり、真面目に直してもむなしいだけなのでこれは再起動一発で直すことにする。で、再起動した後あっさり終わることを祈りつつ以下を試した。

xe@localmachine$ ssh hogeserver
Permission denied (publickey).

…何かpermissionを直し忘れているだろうか?

root@hogeserver# ssh localhost
Permission denied (publickey).

鍵のパーミッションなどを確認しても問題はないはず。SSH固有の問題を疑い、とりあえずローカルで調べることにする。とはいえサーバ機なので自分のパスワードはなく、suしてみることにする。

root@hogeserver# su - xe
cd: can't cd to /home/xe

いや、そんなはずは…/home/xeに行けないのが駄目ならcdしなければいいじゃない。

root@hogeserver# su xe
Cannot execute /bin/bash: Permission denied

完全に詰みました。

盲点は気づかないから盲点と呼ばれる

このあとdpkg -L openssh-serverの結果のパーミッションを全部確認してみたり、strace su xeしてみたり涙ぐましい努力をしてみたのですが、駄目。
で、rootでログインできなくなったらどうしよう…と思いつつもエイヤで再起動、rootログインはできるものの上の3つは相変わらず駄目。そして、このまま格闘しても全く分かる気がしなかったので藁にもすがる思いで"Cannot execute /bin/bash: Permission denied"をググることにした。そして、Cannot execute /bin/bash: Permission denied | 作業日報を開いた私は驚愕の事実を目の当たりにするのであった。
そう、 / のパーミッションが間違っているのである。いやー、これは盲点だわー、ls -l --color /してたけど/は見えないもんなー。という事でこれを直したら無事に全てが動いた。

結論

  • 精神的に焦っている時に大事な作業はしないほうがいい
  • 大事な作業をするとき、rootで作業しているときは常に深呼吸する
  • bashはクソ、zshこそが最強

*1:suid,gidなどは特定のバイナリに付いていることもあるし、ディレクトリに付いていることもあるし、それがシステム全体でどこにあるかパッと分かる人なんていないのではないか。例えばsuにはsuidが付いている。

*2:/etcはshadowなどパーミッションにセンシティブなファイルがあり、/varもどこに何があるんだかよくわからないディレクトリである