Wednesday, February 7, 2024

[SOLVED] PHP: way to get the true /tmp path?

Issue

I'm moving my web app from CentOS 5 to CentOS 7, and new security features regarding the /tmp directory are breaking my code. I'm wondering how best to handle it.

I have PHP code that creates a LaTeX file, then executes commands to turn that into a PDF, and then serves that to the user with appropriate headers. Here are some of the relevant lines of code as it stands now:

$fileroot = "/tmp/addr".getmypid();
ob_start();
/* echo all the LaTeX stuff */
file_put_contents($fileroot.".tex",ob_get_contents());
ob_end_clean();
exec("cd /tmp;uplatex -interaction=batchmode --output-directory=/tmp $fileroot", $output, $return);

The settings in /usr/lib/systemd/system/php-fpm.service include PrivateTmp=true, which causes /tmp within PHP function calls to really be /tmp/systemd-private-6898f2d665d64b998981bc479ddc2306-php-fpm.service-KU8XML/tmp. Yikes! That's fine for security, but exec() uses the /tmp path literally, so it can't find the file that file_put_contents() just created. The PHP function sys_get_temp_dir() just returns /tmp, and I can't find any environment variables with that path in them. Is there a way to get that path programmatically? Or do I need to turn off PrivateTmp? Or is there a better way to do what I need to do? Yes, I could create my own special spot with wide-open permissions, but it seems like it should be cleaner to just use the normal temporary directory.


Solution

The way I see it, there are only two options:

  1. Do not use /tmp but a different directory instead, which you predefine in your application's config file. I have done something similar recently, where I used /var/run/myapplication directory instead of /tmp. (I had to add a cron job to clean it up as well.)

  2. Disable PrivateTmp in the php-frm service. Here's one way of doing this:

    # mkdir  /usr/lib/systemd/system/php-fpm.service.d
    # echo -e "[Service]\nPrivateTmp=no" > /etc/systemd/system/php-fpm.service.d/privatetmp.conf
    # systemctl daemon-reload
    # systemctl restart php-fpm
    
    # systemctl show php-fpm | grep PrivateTmp
    PrivateTmp=no
    


Answered By - Aleks G
Answer Checked By - Clifford M. (WPSolving Volunteer)