fchmod() の謎

SunOS 4.1.4
YAMAMORI Takenori


SunOS 4.1.4 で、一部のデバイスファイルを fchmod() しようとすると、kernel が panic するというバグが未だに直っていません。patch も出ていない模様です。
私自身がまず確認したのは、/dev/audio/dev/fb です。そのほか、/dev/cgsix0/dev/tcx0 でも、そのフレームバッファ・デバイスが存在すればカーネルが panic します

fchmod() とは

UNIX で通常、ファイルのパーミッションを変更するには、chmod コマンドを使いますが、chmod コマンドは、内部で chmod() というシステムコールを行なっています。 ファイルのパーミッションを変更するシステムコールには、この chmod() のほかに、fchmod() もあります。chmod() は、ファイル名を引数とするのに対し、fchmod() はファイルディスクリプタを引数とする点が異なっています。 したがって、プログラム的には、すでに open() しているファイルについては、chmod() よりも fchmod() の方が呼び出しやすいという側面もあります。

fchmod() は、後述のように、/bin/cp -p でファイルをコピーする際に、元のファイルのパーミッションを設定するために呼び出されています。


●panic 現象の再現方法

次のように、/bin/cp を用いてコマンドを実行するとカーネルが panic します。

$ /bin/cp -p /bin/cp /dev/audio
BAD TRAP
....
kernel read fault at addr=0xc, pme=0x0
....

なお、GNU fileutils に含まれる cp の場合は、内部で fchmod() を使っていないので問題は発生しません。 この現象を再現するには、SunOS 標準の /bin/cp を使う必要があります。

そのほか、自分で問題のデバイスファイルを open() し、fchmod() するような簡単なCソースを書いても症状が再現します。

/bin/cp -p を用いる方法では、デバイスファイルに書き込み permission が必要ですが、問題のバグには書き込み permission は 関係無く、ファイルが open() さえできれば、fchmod() で panic します。

○原因は?

カーネルのソースコードが無いので直接原因を究明できませんが、 panic 時に表示されるアドレス等の情報から、どうやら、VFS オペレーションの fchmod() の処理の部分で、操作対象の(デバイス)ファイルを含むファイルシステムが Read Only で mount されているかどうかをチェックしようとしていて、その Read Only かどうかを示すフラグへのポインタの処理が不適切で、/dev/audio などの一部のデバイスファイルでは何故かポインタが NULL ポインタになってしまっており、その部分で不正なアドレスをアクセスして kernel panic するらしい・・というあたりまで解りました。

○対策は?

/dev/audio/dev/cgsix0 等の問題のデバイスを外し、 kernel を再構築すればとりあえず問題は防げます。これはサーバー専用マシンなどで /dev/audio/dev/cgsix0 等を使わない場合の消極的な解決と言えるでしょう。

/dev/audio/dev/cgsix0 を使いたい場合は依然、問題は未解決のままです。 現状、patch は出ていません。おそらく、バグはプログラム的にはほんのちょっとしたことであり、デバイスドライバの本質に関わるようなものではないと思われます。 しかし、ソースコードがないとどうすることもできません。 このバグも、以前の tmpfs のバグと同様に、いつかきっと解決してやろうと思っています。


To 『SunOS 4.1.4 の謎』index

To「謎の処理系 SunOS 4.1.4 with Linux/FreeBSD/Solaris」Home
yamamori