5

I have an image processor PHP script, and it contains the following code:

        if (!is_dir($fullFile)) {
            if (is_readable($fullFile)) {
                $im = getimagesize($fullFile); // Will be FALSE if not an image

In some instances, the script will fail at getimagesize with the following error:

getimagesize(/path/to/file.jpg) [function.getimagesize]: failed to open stream: Permission denied at www.yada.yada/page.php

In this case, the permissions for /path/to/file.jpg are definitely prohibitive (400), so I'd have expected the is_readable test to prevent me getting to that point. Aside from setting permissions differently, what might I do in order to resolve this? Why does it seem that is_readable has an incorrect result? Is it possible that is_readable is operating with the EUID of the file owner, while getimagesize is not? That's the only explanation that makes sense to me, but even that knowledge doesn't help resolve.

Prompted by @hek2mgl I created this ultra-complex script, named readable.php:

<?php echo is_readable("/stora2/Pics/2009/2009-07-26/DSC00532.JPG") . "\n\n"; ?>

Then I switched user to the web server user (actually www-data on this server) and ran it. Result was

1

Then I ran strace as that same user. These are the commands I used. The result is a 70KB+ file, and SO won't let me post it in its entirety, so it is posted at http://pastebin.com/mFqiSBiz

dennis@luke:~$ sudo su - www-data

$ ls -l "/stora2/Pics/2009/2009-07-26/DSC00532.JPG"
-rw------- 1 dennis dennis 524288 2012-02-11 08:18 /stora2/Pics/2009/2009-07-26/DSC00532.JPG

$ file "/stora2/Pics/2009/2009-07-26/DSC00532.JPG"
/stora2/Pics/2009/2009-07-26/DSC00532.JPG: writable, regular file, no read permission

$ php /home/dennis/readable.php
1

$ strace php /home/dennis/readable.php > /tmp/strace.out 2>&1

Not sure what I'm looking for. Please advise.

Dennis
  • 1,071
  • 2
  • 17
  • 38
  • *"Keep in mind that PHP may be accessing the file as the user id that the web server runs as (often 'nobody')."* – Madbreaks Jan 09 '13 at 00:24
  • 2
    The result could also be cached. Try [`clearstatcache()`](http://php.net/manual/en/function.clearstatcache.php) – Phil Jan 09 '13 at 00:25
  • What user owns the file and what user is your web server running as? – Mike Brant Jan 09 '13 at 00:25
  • could you run this code, `var_dump($fullFile, is_dir($fullFile), is_readable($fullFile));` ? – Shiplu Mokaddim Jan 09 '13 at 00:28
  • @shiplu.mokadd.im - result is string(41) "/stora2/Pics/2009/2009-07-26/DSC00532.JPG" bool(false) bool(true) – Dennis Jan 09 '13 at 00:32
  • @MikeBrant - the webserver is running as apache; the owner of the file is dennis. The file is actually on an SMB share. I expected is_readable to fail. – Dennis Jan 09 '13 at 00:34
  • @Phil - thanks I didn't realize this could be cached. I added the code right before is_readable, and no joy - the result did not change. – Dennis Jan 09 '13 at 00:36
  • Are you familar with strace? :) – hek2mgl Jan 09 '13 at 00:37
  • 1
    A [bugreport](https://bugs.php.net/bug.php?id=62199) has already been filed on a problem that might be related to this. – hek2mgl Jan 09 '13 at 00:41
  • Apache and CIFS = a world of pain – Phil Jan 09 '13 at 00:42
  • @hek2mgl I have run strace, but not for a web page or, more accurately, to trace a web server's activities. Initial quick searches don't reveal a way to do this, and the script would be a bear to run from command line. – Dennis Jan 09 '13 at 00:42
  • Isn't it possible to reproduce the problem with a simple cli script? Would suggest – hek2mgl Jan 09 '13 at 00:44
  • @hek2mgl D'oh! Yes I can reproduce. I had my head where it absolutely doesn't belong, there for a minute. Bug report: GREAT FIND! Thanks! – Dennis Jan 09 '13 at 00:46
  • There is also a [SO article](http://stackoverflow.com/questions/10818770/php-is-readable-fails-on-readable-samba-directory) on this. (Questioner is the opener of the bug report) ... Would be nice to hear a solution on this if you can find one.. Good Luck! – hek2mgl Jan 09 '13 at 00:49
  • @hek2mgl I ran strace, but cannot share the full result. I've updated the question with the tease from that. Sorry it's only a tease; I am uncertain what parts of the output are essential, and SO limits my posts to 30,000 bytes. Can't blame 'em. – Dennis Jan 09 '13 at 01:30
  • you can post it to [pastebin](http://pastebin.com/) and share the link. (Great update to question!) really awsome bug! – hek2mgl Jan 09 '13 at 01:34
  • Done, thanks. Link posted in question and here. http://pastebin.com/mFqiSBiz – Dennis Jan 09 '13 at 01:49

1 Answers1

2

Depending on what version of php you are running, this could be a bug, as hek2mgl said in the comments. If you want to workaround this, you can add logic based on the file permissions, with fileperms

Jormundir
  • 430
  • 4
  • 11
  • Got me past the hump, thanks. I used: >>> if (fileperms(&fullFile) & 0x04 == 0x04) { <<< in place of >>> if (is_readable(&fullFile)) { << – Dennis Jan 09 '13 at 01:35