読者です 読者をやめる 読者になる 読者になる

OpenBSD の chroot jail httpd で CGI を動かす(2)

続き

というわけで前回の続きです。前回は結局、「インタプリタ実行ファイルを実行するのに読み取り権は必要?不要?」という疑問がモクモクと湧き上がって CGI とかどうでも良くなったという結末でした。あと、 /dev/fd/X を触れないというエラー。これらについて調べてみました。

実行ファイルの実行って?

そもそも実行ファイルってどういう理屈で実行されてるんじゃろか?ということで OpenBSD のマニュアルをポチポチ検索してみると、どうやら execve(2) というのが担当しているご様子。こいつが新しいプロセスを立ち上げてくれるみたいで、ごにょごにょと説明を読んでみると

  • この人が「新プロセスファイル」として立ち上げることのできる対象は「実行オブジェクト(コンパイル済み)ファイル」か「インタプリタのためのデータファイル」のどちらか
  • この判別には、ファイル先頭の識別ヘッダを用いる。インタプリタのためのデータファイルの場合これが "#!"
  • execve() がこの "#!" (のバイナリ値)をファイルの先頭に見つけると、これはインタプリタのための(以下略)として見なし、その直後に書かれているインタプリタファイルを代わりに新プロセスファイルとして扱い、引数に元々のファイルが渡る。

以上のことが書かれてます。なるほどねー。

で、インタプリタ実行ファイルの実行に読み取り権限は必要?

これが謎でした。だって OpenBSD って、実行できちゃうんですもの。例えば、

$ cat test
#!/bin/sh
echo test
$ sudo chown oogatta:oogatta test
$ chmod 100 test
$ ./test
test

ってなります。 OpenBSD では。で、僕はすっかりこの気分でいたんですけど、なんとこれ、 UbuntuCentOSFreeBSD で試したんですが全部動かないんですよ!

oogatta@oogatta-ubuntu:~$ ./test
/bin/sh: Can't open ./test

これは手元の Ubuntu の実行結果ですが、こうなります。上の実行ファイル実行の手順が Linux でも一緒だ、と仮定してもしなくても、これはこれでなんとなく腑に落ちます。オーナー(自分)権限で動いているインタプリタ実行ファイルがこのスクリプトファイル自身を再度開きにいって、読み取り権限が無いから開けないと言っている。むしろこっちが当たり前です。

不思議に思ったのでさらに検索しましたところ、 shebang について詳しく説明してくれているこんなページがありまして、

The #! magic, details about the shebang/hash-bang mechanism on various Unix flavours

ここの "Setuid(set user id) support" の項に思いっきりそれっぽいことが書いてありました。

だってさ!すごいね!まあこの場合 setuid/gid の話はあんまり関係ない上に、ここはカーネルハッカー的にソースを追う場面なんですが、俺はカーネルとかまじわからん!勘弁してくれ!俺はもうここで納得したので許してください。僕はしがないいちOpenBSDユーザなのです。テオ様には「slacker」とか呼ばれちゃうタイプの人間なんです。人間には限界がある。しかたがない。

とまあそんなわけで、 OpenBSD ではカーネルが開いてインタプリタに渡すしくみがどうやらあるので、インタプリタ実行スクリプトファイルには読み取り権限がいらなかったということかなと勝手に納得しました。だって、前回のあのエラー、

# chroot -u www /var/www /cgi-bin/test-cgi 
/bin/sh: /dev/fd/3: No such file or directory

これもよく裏付けていると思いませんか。 /var/www に chroot されてると、決め打ちでファイルディスクリプタにアクセスいっても無いってことなんですよ。

カーネル:あ、あのファイルさぁ、 /dev/fd/3 に開いて置いておいたからー
インタプリタ:いや、僕そこ行けないみたいなんスけど今…。

ということですね。いやびっくり。

この辺、 chroot 環境でもなんとかすればふつうにファイルディスクリプタが使えるか…、たとえば、

$ mutt -a <(mysqldump mysqldumpoptions) oogatta@oogattattattatta.tta

こういうのが動くのか?というのは試してないんですがネ…。これ、ちょうどファイルディスクリプタの仕組みを使って動いているらしいので。時間とテンションがあれば実際に試してみよう。 C とか書く…、のに手を出すのはやめよう。

参考:
create ‘virtual file’ from bash command output ? / serverfault

chroot 環境でのインタプリタ実行スクリプト CGIパーミッションは 500 にするよ!

方針決定です。前回適当に試した内容の繰り返しですが、

# chmod 500 /var/www/cgi-bin/test-cgi  
# chroot -u www /var/www /cgi-bin/test-cgi 
Content-type: text/plain

CGI/1.0 test script report:

unko
(以下略)

この通り動きます。ブラウザからもアクセス可能。良かった良かった。というわけで次回、 Perl を動かしてみるへ続きます。次々回が「 Tokyo Promenade を動かしてみる」になる予定です。かしこ。