セキュリティー上の問題修正でnamazu 2.0.16 がリリースされました。私自身は使ってないのですが、Xserve 上に置いている知人のページで使っているため、インストールはしていたのでした。なもんで、先日これをアップデートかけてました。
さて、/usr/local/ 以下のコマンドなどは sudo make install でアップデートされたのですが、namazu.cgi はあちこちの DocumentRoot にコピーされているので( コピーしろと namazu の説明書に書かれているため)、それを探して置き換えるのが結構面倒でした。今後も脆弱性の発覚はあるだろうし置き換えはやっていかなきゃいけないだろうから、いつか見落としが出るなぁと。なんとかしないと。
FollowSymlinks を付けてるとは限らないのでシンボリックリンクで逃げる案は却下。DocumentRoot 以下には起動するだけのシェルスクリプトをおいておくかと思いましたが、すると namazu.cgi は「自身の存在するディレクトリの .namazurc を読む」ので、/usr/local/libexec にそれを求めようとして実行に失敗します。「自身の存在するディレクトリ」は、C で言うところの argv[0] というかシェルスクリプトで言うところの $0 を参照するので、実行するコマンドのパスと、argv[0] に異なる物を指定すればいいのですが、さて、シェルスクリプトでそれをどう指定して良いのか分からない。
Perl の場合は
$shell = '/bin/csh';とかして、一旦変数に path をいれてから渡せばそういう振る舞いができるらしい。さすが Perl、意表をついたインターフェイスだ(^^;
exec $shell '-sh'; # ログインシェルのふりをする
しかし、単にそれだけのために Perl を起動するのもなんかもったいない。というわけで、こんなものつくりました。
#include <stdlib.h>これを exec2 というコマンド名でビルドして、
#include <sysexits.h>
int main( int argc, const char *argv[] )
{
if( argc > 3 ) exit( EX_USAGE );
execv( argv[1], &( argv[2] ) );
}
#!/usr/local/bin/exec2 /usr/local/libexec/namazu.cgiという1行のファイル(index.cgi)を用意して実行ビットを立てておく。
すると、apache はこの index.cgi を実行しようとする。カーネルは#! をみて
argv[0] = /usr/local/bin/exec2 (#! の直後)で exec2 を起動する。exec2 は /usr/local/libexec/namazu.cgi を起動するけど、namazu.cgi からみると
argv[1] = /usr/local/libexec/namazu.cgi (#! の引数)
argv[2] = ./index.cgi (自身のファイル名)
argv[0] = ./index.cgiとなる。結果的にうまくいくと。この場合、fork は1回のみ、あとは exec が繰り返されるだけなのでプロセス数は変わらない。
ただ、これぐらいのこと、実は sh だけでできそうな気がしてならないのだけどなぁ。
と思って調べてたら、Mac OS X の sh の exec 内部コマンドには -a オプションなんてあるじゃないですか(^^;
そうか、bash 拡張だったから気がつかなかったのね。実際、NetBSD 1.6.1 で追試したところ ash の exec には -a なんてオプションはありませんでした。上記プログラムの方が bash より小さいし、bash があるとも限らない氏、もうビルドしちゃったので当分そのままでいきますけど。