Привязка монтирования не отображается при создании из сценария CGI в 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>"

Первые две команды создают точку монтирования и выполняют монтирование. Последние две команды проверяют результат. Скрипт выполняется без проблем. Однако монтирование не видно и не доступно в отдельном процессе оболочки. Выполнение последних двух команд в отдельной оболочке не показывает, что монтирование доступно. Если я попытаюсь выполнить «rm -rf /shares/target», я получу «rm: невозможно удалить ‘/shares/target/’: устройство или ресурс заняты». Выполнение «losf | grep /shares/target» не генерирует выходных данных. В отдельной оболочке я переключился на пользователя apache, но монтирование по-прежнему недоступно. Я проверил, что процесс apache не находится в chroot, зарегистрировав вывод «ls /proc/ $$/root". Он указывает на "/".

Я бегу:

  • Апач 2.4.6
  • ЦенОС 7
  • httpd-2.4.6-31.el7.centos.1.x86_64
  • httpd-tools-2.4.6-31.el7.centos.1.x86_64

Я включил ведение журнала для отладки, но error_log ничего не указывает.

Заранее спасибо.


person pdeline    schedule 30.09.2015    source источник


Ответы (1)


Такое поведение связано со следующей строкой в ​​модуле 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 полезна с точки зрения безопасности, как описано здесь:

/tmp традиционно был общим пространством для всех локальных служб и пользователей. На протяжении многих лет он был основным источником проблем с безопасностью для множества сервисов. Атаки по символическим ссылкам и DoS-уязвимости из-за угадываемых временных файлов /tmp являются обычным явлением. Изолируя /tmp службы от остальной части хоста, такие уязвимости становятся спорными.

Вы можете безопасно удалить директиву PrivateTmp из юнит-файла (на самом деле не изменяйте юнит-файл — создайте новый в /etc/systemd/system/httpd.service, затем systemctl daemon-reload, затем systemctl restart httpd).

person larsks    schedule 30.09.2015