Cannot access or copy files with PHP on Ubuntu 18

apache-http-serverlinuxpermissions

I have to deal with a legacy project, where a PHP API creates a CSV export from MySQL and provides the file to download it later.

The problem is that the API can't copy the CSV file to the directory, from which it can be downloaded (through Apache)

The process goes like this:

  1. Someone clicks a button on a website to create a csv export.
  2. The API creates a SQL statement and executes it with shell_exec(mysql …);
  3. The Database creates a CSV file with the data and puts it into /tmp/
  4. The API copies the file into a dedicated download directory for apache
  5. The API sends a mail with a download link to the user, who clicked the button.

Everything of the above works except step 4.

What I found in the API was:

$exportCommand = "mysql ....";
// mysqlExportTmpDir = /tmp
// mysqlExportTargetDirectory = download directory for apache
$moveExportFileCommand = "cp ".$this->mysqlExportTmpDir."/$filename ".$this->mysqlExportTargetDirectory;
shell_exec("( $exportCommand; $moveExportFileCommand; $sendNotificationCommand) &");

As I said the MySQL Command works, the mail notification works, but the cp command doesn't.

When I look into the logs I see this error:

cp: cannot stat '/tmp/610278f414d84.csv': No such file or directory

I also tried shell_exec("ls /tmp/*.csv"); to check if the older export files are visible to the API, but then I get this:

ls: cannot access '/tmp/*.csv': No such file or directory

There are definitely CSV files in there. Therefore I thought it might be a permission problem and tried to execute this in the terminal: sudo -u www-data cp /tmp/610274ad5a8a5.csv /path/to/api/download. I copied the cp command from the logs, therefore it should be exactly the same.

That works. Now I'm confused because www-data runs Apache and with shell_exec("whoami") I also get www-data from the PHP API. Maybe the sudo -u www-data cp ... command doens't work as I expected (I expected to have the same permissions as that user). But I don't know.

Does somebody know, why PHP can't access the csv Files in /tmp and copy them to a different directory?

The target directory belongs to the group www-data and files in there can be downloaded from a browser.

I know the approach to export data from a database is strange, but it seemed to work until a year ago. Now there is no one from this project in my company anymore and I don't know what changed.

Best Answer

There is a private tmp directory for Apache located in /tmp/*apache2.service*/tmp. This exists because of the private tmp setting in /lib/systemd/system/apache2.service. I found a little article here.

Whenever I call copy(/tmp/....) in the PHP script it will look in the Apache specific private tmp directory. Apache can't see contents of /tmp with this option enabled.

Therefore I can only disable this option or make MySQL dump the CSV files elsewhere.

Related Question