何があったか
超絶古い C の CGI をパブリッククラウドへ移行させる作業の中で、その CGI が mkstemp()
関数を使ってテンポラリファイルを作成しようとしてエラーになりました。以下は頑張って strace
して取得したシステムコールです。
open("/var/tmp/hoge/temp_k6KF97", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 ENOENT (No such file or directory)
以前の環境は CentOS5.5 の Apache2.2 で、新しい環境は CentOS7.1 の Apache2.2 です。
(本当は Apache2.4 を使いたかったのですが諸般の事情で 2.2 をソースインストールすることに)
書き込みディレクトリのオーナーやパーミッションは問題ない (apache ユーザーが書き込みできる) のにエラーが出ます。
試行錯誤
試しにディレクトリのパーミッションをフルアクセスにして、mkstemp()
関数を使ったテストプログラムを作ってターミナル上で叩いてみたところ、問題なくテンポラリファイルが作成できました。
しかしこれをWebサーバーから叩ける場所に置いて、CGI としてブラウザーから実行させるとやはりファイルが作成されません。ファイルディスクリプタが獲得できないのです。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
char filename[] = "/var/tmp/hoge/temp_XXXXXX";
int i = 30;
int fd;
sleep(i);
fd = mkstemp(filename);
printf("Content-type: text/plain\n\n");
printf("result: fd: %d\n", fd);
}
解決策が見つかる
ログイン権限を持たないユーザーが /var/tmp に書き込みできないのだろうか…とか途方に暮れてあれこれ調べていたところ、「Yahoo!知恵袋」の質疑応答にあたりました。
- CentOS7で/tmpに書けないCentOS7を使ってWEBアプリを実行したところ... - Yahoo!知恵袋
- centos7 の apache から php などで /tmp/ でデーターを落とすと/tm... - Yahoo!知恵袋
これを読んでいてハッと気づきました。そういえば CentOS7 でソースインストールした Apache2.2 を systemd でコントロールできるようにするために、なんかファイルを置いたんだった!
慌てて /etc/systemd/system/httpd.service
を覗くと、果たして上記のページに書かれていた設定がありました。
[Unit]
Description=Apache Web Server 2.2
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl -k start
ExecReload=/usr/local/apache2/bin/apachectl graceful
ExecStop=/usr/local/apache2/bin/apachectl -k stop
PrivateTmp=true # <- これ
LimitNOFILE=infinity
[Install]
WantedBy=multi-user.target
これを、
-
PrivateTmp=false
にする。 sudo systemctl daemon-reload
sudo systemctl restart httpd
してから改めて CGI を動かしたところ、テンポラリファイルが /var/tmp
配下に作成されました。
systemd の定義ファイルを見よう見まねで作っていて、各項目の意味をちゃんと理解していなかったのがハマった原因です。ちゃんと勉強します…。
要するにどういうことか
CentOS7 から採用された systemd で、登録したサービスが使う /tmp
や /var/tmp
を、OS標準のものではなくサービス専用のものを用意して提供してくれる仕組みです。別プロセスからこの配下のファイルを操作されてしまうとセキュリティの問題が発生することがあるため、それを避けるための対策として提供された機能のようです。
(参考: テンポラリファイルの扱いについてまとめた記事: 情報セキュリティ技術動向調査(2008 年下期):IPA 独立行政法人 情報処理推進機構)
インターネット側から不特定多数の人が叩くプログラムでテンポラリ領域を使うのは危険、ということのようです。