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:
apache:apache
777
and owner root
(by default, owner is set to apache
)/var/www/html
and /tmp
are inside open_basedir
, upload_tmp_dir
is not set) + logs777
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/tmpArray ( [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:
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!
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