PHP fopen always fails with permission denied

apache-2.2PHPsuexec

I am in the process of migrating a couple of WordPress blogs over to AWS and have run into an issue with file permissions that has successfully foiled me for the last couple of hours.

The simplest possible fopen call always fails with "failed to open stream: Permission denied":

<?php $handle = fopen('test.txt', 'w') or die('Can\'t open file'); ?>

I have tried/checked the following

  • The directory I'm writing to has the correct file permissions (755) and the correct ownership. This is true all the way up the path to /home.
  • I am writing the correct directory as confirmed by getcwd()
  • The test PHP script hash the same ownership as the path I am trying to write to and correct permission (644).
  • I'm running mod_suexec to ensure the script is executed with the same user and group as the path I am writing to. The functions getmyuid() and getmygid() return the correct user and group IDs (Edit: This is wrong see below).
  • PHP safe mode is disabled in php.ini.
  • fopen is not a disallowed PHP function.
  • The use of open_basedir is disabled.

Is there anything I have missed that might be causing this? I suspect I've been staring at this for so long I'm missing something obvious.

Update: After applying womble's suggestions I am starting to think this issue is more nefarious than just bad permissions or a PHP misconfiguration. I did manage to get the above code to write out a file, however even though the PHP script executed with the correct user and group the resulting files ownership and group were set to that of apache. If I execute the same test script from the command line the emitted file has the correct permissions. This leads me to believe it is an issue with my use of mod_suexec.

Edit: My use of getmyuid() and getmygid() are incorrect as they only return the user and group of the script file not the permissions it is running with. A more correct approach is to use comething like this:

<?php echo exec('ps -up '.getmypid()); ?>

Best Answer

Good question -- shows you've done your homework.

I can't think of anything "obvious" that you've failed to check, so I can only give you some more advanced debugging advice.

  • Fire up strace on the PHP process, and see exactly what it's doing under the hood.
  • Write a bit of code that does an fopen(..., 'r') to triple-check that your directory tree permissions are, in fact, OK.
  • su to the user in question and try doing some stuff on the command line. If that works, then you know your script isn't running with the permissions you think it is.
  • Check that there are no extended ACLs on the file, directory, or leading path components (getfacl is the tool to use). It's uncommon, but every once in a while they'll leap up and rip your face off. If you do have ACLs, use setfacl -x to get rid of them once you've verified they're unnecessary.