LoginSignup
7
5

More than 5 years have passed since last update.

apache「mountしたよ!」root「してないんだよなあ」apache「してるじゃん!ファイルも見れるよ!」

Posted at

root「ないです。apacheになって見てやんよ」
su apache 「ないです」

結論

Systemd入門(5) - PrivateTmpの実装を見る - めもめも
にすべてが書いてある。
おわり!

これは、あくまでsystemdから起動するプロセスに対して設定するべき内容です。普通に上記の操作をすると、システム上のすべてのプロセスに対して、ファイルシステムの状態が変更されてしまいます。ここで登場するのが、「ファイルシステムのnamespace」(以降は単に「namespace」と表記)の機能です。これを使うと、プロセスごとにファイルシステムの構成状態(マウント状態)を分離することができます。systemdでは、この機能によって、起動プロセスから見えるファイルシステムの構成状態(マウント状態)のみを変更しています。

,

PrivateTmpの機能も同様に、namespaceを利用しています。「/tmp/systemd-private-XXXXXX」(XXXXXXはランダム)という空のディレクトリを用意して、該当プロセスに対しては、/tmpをここにバインドマウントします。これで、このプロセスに対して、/tmpの中身は、/tmp/systemd-private-XXXXXXになります。/var/tmpも同様に別の空ディレクトリにバインドマウントします。

,

また、このシェルからは、次のように/tmpがバインドマウントされているエントリが確認できますが、別の端末からログインした方では、このエントリは見えません。これからもファイルシステムのnamespaceが分離されていることが分かります。

,

プログラム内で、具体的にnamespaceの分離を行う部分をコメントに記してあります。(*1)でnamespaceを分離した後に、(*2)で/以下に「MS_SLAVE」というマークをつけています。これは、このnamespaceで行った変更(追加のバインドマウントなど)を元のnamespaceには反映しないという指定です。これによって、(*3)のバインドマウントは、このプロセスのnamespaceのみで実施されて、他のプロセスからは見えなくなります。

,

上記で説明したように、PrivateTmpを利用してプロセスを起動すると、そのプロセスが追加のバインドマウントを行っても、それは他のプロセスからは見えません


/usr/lib/systemd/system/httpd.service
PrivateTmp=truePrivateTmp=falseにすると問題が発生しない。
他の一部機能がtrueな場合も同様の状態が発生すると思われる。


PrivateTmpの仕様というか、副作用により、ブラウザ(Apache)を経由して実行されるmountはそのプロセスからしか参照できない。
プロセス内でmountすることでリードオンリーにしたり、/tmp/tmp/systemd-private-XXXXXXをmountして、/tmpへの書き込みにprivateTmpを実現しているのだが、このとき、PHPでもあるようなnamespaceを使うことで、他プロセスとはmount状況を独立させることができる。

この影響はプロセス内で残り続けるので、PHPでexec('mount hogehoge')としても、そのmountは同じnamespaceのプロセス内でしかmountされていることにはならない。

したがって、端末のrootやapacheユーザーであろうと、mount状況は見えない。

環境

  • CentOS7 64bit
  • Apache/2.4.6 (CentOS)
  • systemd 219

問題

書いていたコード

ブラウザから入力された内容でmountを行い、ブラウザでファイル一覧を確認したり、バッチ処理でデータの読み書きを行う。

CentOS7移行前まで稼働実績あり

起こったこと

バッチでのmount領域内の処理が失敗する。
というか、mountコマンドでmountされているかの確認を行うが、されていないと出るので処理が行われない。

sshで入り確認するも、手動のmountdfではやはり確認出来ないが、
ブラウザから確認すると、同様のmountチェックコードでも正常にmountされていることが確認できてしまう。

Apacheでしかmountできないわけではなく、Apacheでのmount状態がApache以外では確認できないような状態だった。
(Apacheと端末で同じ領域に別々にmountしたりできてしまった)

確認した方法

最小構成のPHPを公開領域に置き、ブラウザでアクセスした場合と手動で実行した場合で問題が再現したので、Apacheの問題とした。


<?php

exec('/usr/bin/sudo /bin/mount -t nfs 192.168.1.123:/nas /nas');

echo shell_exec('/usr/bin/sudo /bin/mount');


PrivateTmpはデバッグ時のファイル書き出しで引っかかって覚えていたのですが、デバッグ以外では/tmpに書き込まないからと放置していた結果の落とし穴でした。

PrivateTmpの無効方法およびその他の落とし穴は
お前らもさっさとハマって泣くべきCentOS7の落とし穴4つ - Qiita
をどうぞ。
/tmp問題はこっちを先に見ていたのに忘れてハマって泣いたんですけど。

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5