Вопрос или проблема
У меня нет open_basedir, PHP может получить доступ к /etc /usr /proc /home и т.д., но не к /tmp.
tmpfs подключен к /tmp (/tmp тип tmpfs (rw)). Это также причина, по которой я хочу использовать папку /tmp.
Мои файлы принадлежат http (пользователь для nginx и php) и доступны для чтения всеми.
sudo -u http cat /tmp/file
работает, но ничего внутри PHP-скрипта нет (например, file_exist() или file()).
редактировать: ошибка в журнале:
PHP Warning: file(/tmp/ydlw/pid): failed to open stream: No such file or directory in /srv/http/ydlw/status.php on line 267
редактировать2: я проверил проблему другим способом. Я сделал
touch("/tmp/boo");
file_exist("/tmp/boo");
и file_exist возвращает true, так что файл создан. Затем я посмотрел внутри /tmp, и никакого файла “boo” там не оказалось. Это то, чего я боялся, PHP не «видит» точку монтирования. Почему это происходит и как я могу это исправить?
Я нашел причину, ну, кто-то дал мне общий намек.
Это не вина PHP или tmpfs. Виноват был systemd и его система безопасности PrivateTmp
.
Для тех, кто столкнулся с такой же проблемой, как и я, служба PHP (а возможно, и некоторые другие) имеют опцию PrivateTmp
включенной в скрипте systemd (/usr/lib/systemd/system
).
В этом случае создается новый /tmp
и изолируется от другого. Все данные внутри удаляются, как только служба останавливается.
Это мера безопасности, так как /tmp
может содержать много конфиденциальной информации, а PHP-скрипты не всегда безопасны.
Чтобы отключить это, просто скопируйте скрипт в /etc/systemd/system
(чтобы избежать перезаписи ваших изменений после обновления) и установите для PrivateTmp
значение false
.
Вы также можете установить, чтобы две и более службы делили один и тот же /tmp с помощью JoinsNamespaceOf
.
Для получения дополнительной информации > man systemd.exec
Я знаю, я немного запоздал, но сейчас я тоже над этим работаю, поэтому хочу добавить одну идею. Как написал @eephyne, PrivateTmp
— это мера безопасности, выключение которой, возможно, не лучший выбор. Чтобы преодолеть проблему, когда одна служба не может получить доступ к файлам в /tmp
другой службы, systemd предлагает опцию JoinsNamespaceOf=
. Используя это, мы можем определить службы, которые делятся /tmp
, /var/tmp
… но изолированы от /tmp
других служб.
Чтобы добавить JoinsNamespaceOf=
к юнитам systemd, не редактируйте файлы юнитов напрямую, всегда используйте systemctl edit ...
, чтобы избежать путаницы при обновлениях ОС.
Ответ или решение
Проблема доступа PHP-скрипта к каталогу /tmp
Проблема:
Вас тревожит, что PHP-скрипты не могут получить доступ к каталогу /tmp, несмотря на то, что ограничение open_basedir
не установлено, и другие пути, такие как /etc, /usr и /proc, доступны. Вы отметили, что:
- tmpfs смонтирован на /tmp с правами на запись (rw).
- Файлы принадлежат пользователю HTTP, который является пользователем для nginx и PHP и доступны для чтения всем.
- Запуск
sudo -u http cat /tmp/file
работает, но внутрь PHP возвращаются ошибки, подобные:PHP Warning: file(/tmp/ydlw/pid): failed to open stream: No such file or directory
.
Позднее было установлено, что проблема связана с настройкой PrivateTmp
в systemd. Давайте разберёмся, что это значит и как решить эту ситуацию.
Теория:
Systemd предоставляет ряд опций для повышения безопасности различных сервисов, в том числе PHP. Одной из таких опций является PrivateTmp
. Данная опция создаёт изолированную временную файловую систему для процесса, что предотвращает доступ к глобальному /tmp. Таким образом, каждый сервис может использовать свой собственный приватный каталог временных файлов, и это исключает возможность доступа к процессам из других сервисов, снижая риск утечки информации.
Однако из-за этого механизма PHP-скрипты, работающие в контексте этой изолированной среды, не могут видеть файлы, которые находятся в общем /tmp, что может вызывать описанные вами проблемы.
Пример:
Если в настройках сервиса PHP или любого другого сервиса, который использует /tmp совместно, задана опция PrivateTmp=true
, то каталоги временных файлов будут отделены и недоступны для доступа извне.
Чтобы проверить, действительно ли PrivateTmp
является источником проблемы, можно временно установить для него значение false
.
Применение:
Для изменения поведения службы PHP или другой службы:
-
Копирование файла единицы из /usr/lib/systemd/system в /etc/systemd/system:
Это необходимо сделать для предотвращения перезаписи настроек при обновлениях системы.
sudo cp /usr/lib/systemd/system/<service_name> /etc/systemd/system/
-
Изменение значения PrivateTmp:
Вредное изменение конфигурации можно сделать обычным текстовым редактором, например,
nano
илиvi
.sudo nano /etc/systemd/system/<service_name>
Найдите строку
PrivateTmp=true
и измените её наPrivateTmp=false
. -
Перезагрузка службы:
После изменений нужно перезапустить службу, чтобы они вступили в силу.
sudo systemctl daemon-reload sudo systemctl restart <service_name>
-
Альтернативный подход с JoinsNamespaceOf:
Если у вас есть несколько служб, которым необходимо совместно использовать /tmp, вместо отключения
PrivateTmp
, вы можете использоватьJoinsNamespaceOf
. Это позволит нескольким службам разделять один и тот же временной каталог, не нарушая общей безопасности.Воспользуйтесь командой
systemctl edit <service_name>
, чтобы добавить строкуJoinsNamespaceOf=<имя другой службы>
в конфигурацию службы.Это более безопасное решение, которое сохраняет изоляцию временных файлов от других сервисов, но позволяет отдельным сервисам работать в общем пространстве временных файлов.
Заключение:
Использование systemd и его опции PrivateTmp
— это эффективный способ увеличения безопасности серверной инфраструктуры. Однако, как и при любом другом изменении в настройках безопасности, следует тщательно взвесить все за и против, перед тем как менять параметры конфигурации службы. Если возможна альтернатива через JoinsNamespaceOf
, это предпочтительнее с точки зрения безопасности.
Важно помнить о том, что изменения в службе через systemd лучше всего делать через стандартные команды управления systemctl, чтобы избежать проблем в будущем и сохранить конфигурации в обновлённом состоянии при системных обновлениях.