Search code examples
phpapachecentos7php-7.1fpm

PHP: unable to move file to different folder


I'm trying to move a file uploaded with PHP to a different folder, but somehow this will not work, resulting in:

move_uploaded_file(upload/tmp/phpxEGMLG): failed to open stream: Permission denied

So, apparently I do not have proper permissions for upload/tmp (which is in fact /var/www/html/upload/tmp).

I've set permissions to 777 and owner root:root for /var/www/html/upload/tmp to be absolutely sure there couldn't be a problem.
But that didn't solve it...

Other things I've tried:

  • Set owner to apache:apache
  • Change source file permissions to 777 and owner root (by default, owner is set to apache)
  • Checking PHP settings (pretty much default, /var/www/html and /tmp are inside open_basedir, upload_tmp_dir is not set) + logs
  • Checking Apache settings + logs
  • Moving the file within the same folder --> this works!
  • Moving it to a different other folder --> doesn't work
  • Setting all parent directories to 777 and owner root or apache

And I created a test script:

<?php

echo 'TESTING FILE MOVE' . '<br><br>';

echo getcwd() . '<br>';
echo get_current_user() . '<br>';

error_reporting(E_ALL);

file_put_contents('/tmp/tst.txt', 'this is a test');
chdir('/var/www/html/upload/tmp');
echo getcwd() . '<br><br>';
rename('/tmp/tst.txt', 'tst-2.txt');

print_r(error_get_last());

It gives an output like:

TESTING FILE MOVE

/var/www/html
root
/var/www/html/upload/tmp

Array ( [type] => 2 [message] => rename(/tmp/tst.txt,tst-2.txt): Permission denied [file] => /var/www/html/test.php [line] => 13 )

This tells me under which user the script is running and I'm in the right directory. It also omits the extra checks move_uploaded_file uses, focussing on the moving of the file.

Some info about my setup:

  • CentOS 7
  • PHP 7.1
  • PHP-FPM
  • Apache 2.4.6

It uses a separate temp directory for PHP-FPM, like /tmp/systemd-private-xxxx-php71-php-fpm.service-yyyy/tmp/. Perhaps there is some reason it cannot move files outside this directory? I can't find anything on that though...

I hope someone can provide me with a clue as to what might be going on!


Solution

  • It turns out to be SELinux.

    More or less the same question answered here: https://unix.stackexchange.com/questions/50639/httpd-cant-write-to-folder-file-because-of-selinux

    I did have the webserver folders setup with SELinux to be available to Apache, while also allowing FTP read/write. But I needed to set the upload folder (and folders underneath it) to allow read/write by Apache, which can be accomplished by something like this (note the rw bit in the command):

    chcon --user system_u --type httpd_sys_rw_content_t -R upload
    

    Also, a handy command for checking:

    ls -Z
    

    This now shows:

    drwxr-xr-x. apache  apache  system_u:object_r:httpd_sys_rw_content_t:s0 upload