从 Apache 中的 CGI 脚本创建时绑定装载不可见

Bind mount not visible when created from a CGI script in Apache

我的应用程序允许用户将源目录绑定挂载到目标挂载点。这一切都正常工作,除了挂载在更正它的进程之外不存在。

我已将问题归结为一个非常简单的脚本。

#!/bin/bash
echo "Content-type: text/html"
echo ""
echo ""

echo "<p>Hello</p>"

echo "<p>Results from pid #{$$}:</p>"
echo "<ul>"
  c="sudo mkdir /shares/target"
  echo "<li>Executed '$c', Results: " $(eval $c) "</li>"

  c="sudo mount --bind /root/source /shares/target"
  echo "<li>Executed '$c', Results: " $(eval $c) "</li>"

  c="sudo mount | grep shares"
  echo "<li>Executed '$c', Results: " $(eval $c) "</li>"

  c="sudo cat /proc/mounts | grep shares"
  echo "<li>Executed '$c', Results: " $(eval $c) "</li>"
echo "</ul>"

前两个命令创建挂载点并执行挂载。最后两个命令验证结果。脚本执行没有问题。但是,挂载在单独的 shell 进程中不可见或不可用。在单独的 shell 中执行最后两个命令不会显示挂载可用。如果我尝试执行 "rm -rf /shares/target" 我会得到 "rm: cannot remove '/shares/target/': Device or resource busy”. Executing "losf | grep /shares/target”不生成任何输出。在单独的 shell 中,我已切换到 apache 用户,但挂载仍然不可用。我通过记录输出验证了 apache 进程不在 chroot 中"ls /proc/$$/root". 指向"/".

我是运行:

我将日志记录转为调试,但 error_log 没有显示任何内容。

提前致谢。

此行为是由于 httpd.service systemd 单元中的以下行:

PrivateTmp=true

来自 systemd.exec(5) 手册页:

   PrivateTmp=
       Takes a boolean argument. If true, sets up a new file
       system namespace for the executed processes and mounts
       private /tmp and /var/tmp directories inside it that is not
       shared by processes outside of the namespace.
       [...]
       Note that using this setting will disconnect propagation of
       mounts from the service to the host (propagation in the
       opposite direction continues to work). This means that this
       setting may not be used for services which shall be able to
       install mount points in the main mount namespace.

换句话说,httpd和子进程进行的挂载不会 对主机上的其他进程可见。

从安全角度来看,PrivateTmp 指令很有用,如 here:

所述

/tmp traditionally has been a shared space for all local services and users. Over the years it has been a major source of security problems for a multitude of services. Symlink attacks and DoS vulnerabilities due to guessable /tmp temporary files are common. By isolating the service's /tmp from the rest of the host, such vulnerabilities become moot.

您可以安全地从单元文件中删除 PrivateTmp 指令(好吧,实际上不要修改单元文件——在 /etc/systemd/system/httpd.service 创建一个新的,然后 systemctl daemon-reload , 然后 systemctl restart httpd).