php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #41822 include()/require() cause permission denied error (bug #39351 not fixed!)
Submitted: 2007-06-27 13:17 UTC Modified: 2007-10-08 02:58 UTC
Votes:10
Avg. Score:5.0 ± 0.0
Reproduced:10 of 10 (100.0%)
Same Version:5 (50.0%)
Same OS:4 (40.0%)
From: ab5602@php.net Assigned: ab5602
Status: Closed Package: *Directory/Filesystem functions
PHP Version: 5.2CVS-20070627 OS: Solaris 10
Private report: No CVE-ID:
 [2007-06-27 13:17 UTC] ab5602@php.net
Description:
------------
When including files in directories that have access only permissions (no read or write), includes fail with a permission denied when trying things like
include ('../include_me.inc');
Directory permissions for the webserver process are access only (--x).
When including an absolute path, or relative path descending into the directory tree, include works ok eg:
include ('access_only/level2/include_me.inc');

The return value of "is_readable('../include_me.inc');" returns true, however include() fails.

Everything works find up to and including PHP 5.1.6, as of PHP 5.2.0 this problem occurs.

Anthony D. has access to our SPARC system and a test area in which this bug is reproduced has been set up.  He should contact me at my work email address for further information.


Expected result:
----------------
The files should be included, as they were in versions prior to and in  5.1.6.

Actual result:
--------------
Warning: include(../include_me.inc) [function.include]: failed to open stream: Permission denied in /access_only/level2/index.php on line 15


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-06-27 13:46 UTC] ian at onlineloop dot com
CVS version still produces the error.
 [2007-09-12 11:06 UTC] ian at onlineloop dot com
Verified that this is still not working in 5.2.4, nor in the latest CVS version, php5.2-200709121030.

We made a system available on a Sun E3500, partially for the purposes of fixing this bug.  The last login from anyone from the PHP team was on 5 July 2007.

Is there any time plan to fix this bug?  We are running on Solaris 10
and are stuck on PHP 5.1.6 because of this problem, so the situation for us is critical.
 [2007-09-30 14:51 UTC] ab5602 at wayne dot edu
I am having this problem on *ONE* of two load-balanced servers that are setup exactly the same and that share an NFS mounted filesystem in Solaris 9.  The permissions on all the subdirs, all the way from the root directory are at least 'r' and 'x' and are the same on both servers.  Both machines are running the same PHP/Apache binary and are at the same OS patch level.

The following code properly returns the path on one of the machines, but not the other:

echo getcwd();

Could this have something to do with NFS?
 [2007-09-30 17:16 UTC] ab5602 at wayne dot edu
I think I found the culprit that is bubbling up to PHP here. It effects users with: 

  - At least Solaris 9 to early versions of 10
  - NFS mounted directories
  - Any setuid application (including apache/php)

From my previous post, I showed how one server was able to getcwd() in PHP and other other wasn't.  The root cause is this bug:

http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6226092

I tested the code under Solaris 9 and was able to reproduce it at the OS level.  The one machine where include("../file.php") works on was able to successfully execute the solaris bug test code in the NFS mounted directory:

# pwd
/usr/local/www/sites
# ./solaris-nfs-getcwdtest 
CWD = /usr/local/www/sites
# 

The machine where include("../file.php") gives the "permission denied " error fails the getcwd command in the directory:

# pwd
/usr/local/www/sites
# ./solaris-nfs-getcwdtest 
getcwd failed!!!
#

I'm not sure if anything can be done with the PHP source here to solve this since the bug is at the OS level.  Unless there is some other way to get the CWD for PHP in the above situation.
 [2007-09-30 22:05 UTC] ian at onlineloop dot com
NFS has nothing to do with it, this bug is definately *not* at the OS 
level.  We have all file systems mounted locally, and still have the 
problem.

NFS may however cause other problems, particularly userid mapping, 
which are more difficult to solve and need to be solved at the OS 
level.

All of this stuff worked just fine up until PHP 5.1.6, since PHP 
5.2.0 it's broken, and there is apparently no activity to fix this 
bug.
 [2007-09-30 23:46 UTC] ab5602 at wayne dot edu
Ok, or, these may be the same problem caused by 2 different root issues.  In your initial post, you mentioned "Directory permissions for the webserver process are access only (--x).".  I just lifted the following out of PHP source for tsrm_virtual_cwd.c:

 /* cwd_length can be 0 when getcwd() fails.
  * This can happen under solaris when a dir does not have read permissions
  * but *does* have execute permissions */

Have you tried adding r-x to every subdir below and including the path?

Previous versions of PHP including 5.0.5 worked for me with a relative include() parameter, but getcwd() still returned nothing even then.  This did not really cause a problem until include() broke for me.  I believe that PHP now rebuilds a fully qualified path based on getcwd() when it tries to open the file stream and when you are using relative includes.  This may have changed since earlier versions.  I think this issue is probably related somehow to broken Solaris functions that don't work if suid:

Also, have a look at:  #41899 "Can't open files with leading relative path of '..' and '..' is not readable."

They all seem related somehow.
 [2007-10-01 11:37 UTC] ian at onlineloop dot com
>ab5602> Have you tried adding r-x to every subdir below and 
including the path?

This is not an option here.  First issue is user data security.  All 
users have ftp access to the system, and as a reqult of cross 
cooperations, users need to be able to go through the users root 
directory (note that this is not the system root!), meaning if all 
directoriues were r-x, then users could easily see and access data 
that is not relevant to them (other access issues that are obvious 
here have been taken care of using system groups).  Second issue is 
we have tens of thousands of directories like this, and changing the 
permissions to something else is simply not possible because the 
users all have individual requirements, and most have set their own 
permission schemes.  Third issue is *this used to work!!!*

>ab5602> Also, have a look at:  #41899 "Can't open files with leading 
relative path of '..' and '..' is not readable."

The bugs are related.  I am following both of them as they are both 
relevant to us.

>ab5602> ...but getcwd() still returned nothing even then.
Getcwd() needs read permissions on the directory, however in a shell 
in a directory with such permissions, pwd still returns the correct 
directory even if nothing else can be read, and files with read 
permission can also still be read:

root@www:/home/ian/testdir# ls -la
total 10
drwx--x--x   3 root     root         512 Oct  1 13:17 .
drwxr-xr-x   6 ian      staff       1536 Oct  1 12:56 ..
-rw-r--r--   1 root     root          24 Oct  1 13:15 afile
drwx--x--x   2 root     root         512 Oct  1 13:17 testd2
root@www:/home/ian/testdir# cd testd2/
root@www:/home/ian/testdir/testd2# ls -la
total 6
drwx--x--x   2 root     root         512 Oct  1 13:17 .
drwx--x--x   3 root     root         512 Oct  1 13:17 ..
-rw-r--r--   1 root     root          15 Oct  1 13:17 afile2
root@www:/home/ian/testdir/testd2# cd ../../
root@www:/home/ian# su - ian
Sun Microsystems Inc.   SunOS 5.10      Generic January 2005
ian@www: cd testdir
ian@www: pwd
/home/ian/testdir
ian@www: ls -la
.: Permission denied
total 2
ian@www: cat afile
Good bye cruel world!!!
ian@www: cd testd2
ian@www: pwd
/home/ian/testdir/testd2
ian@www: cat afile2
Frodo lives!!!
ian@www: ls -la
.: Permission denied
total 2
ian@www: logout
root@www:/home/ian#

To me, the problem is not something from Sun or Solaris.  The 
problems are in the way PHP is handling access to the files and 
directories.  This needs to be fixed so everything works correctly 
again.
 [2007-10-01 17:33 UTC] ab5602 at wayne dot edu
Hi, the 'pwd' command works just fine for me too on any platform.  However, suid'd use of the getcwd() function I think is the issue.  The below demonstrates what I think is the going on with how Solaris behaves vs. how PHP expects the getcwd() command to behave.

The following code was compiled and run on both Linux and Solaris platforms under a local filesystem and called cwdtest:

#include <stdio.h>
main()
{
        char str[200];

        if (getcwd(str, sizeof(str)) == NULL)
                printf("getcwd failed!!!\n");
        else
                printf("CWD = %s\n",str);
}

------ Linux ------

# uname -a
Linux messaging2.wayne.edu 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686 athlon i386 GNU/Linux
# find ./localfs -ls
 32001    8 d--x--x--x   3 nobody   nobody       4096 Oct  1 13:05 ./localfs
 32002    8 d--x--x--x   2 nobody   nobody       4096 Oct  1 13:12 ./localfs/test123
 32004   12 -rwsr-xr-x   1 nobody   nobody       4878 Oct  1 13:06 ./localfs/test123/cwdtest
# su nobody
# cd /localfs/test123
# ./cwdtest
CWD = /localfs/test123
# pwd
/localfs/test123
#


------ Solaris 10 ------

# uname -a
SunOS opteron 5.10 Generic_118855-14 i86pc i386 i86pc
# find ./localfs -ls
449384    1 d--x--x--x   3 nobody   nobody        512 Oct  1 13:13 ./localfs
449386    1 d--x--x--x   2 nobody   nobody        512 Oct  1 13:13 ./localfs/test123
449388    7 -rwsr-xr-x   1 nobody   nobody       6552 Oct  1 12:57 ./localfs/test123/cwdtest
# su nobody
# cd /localfs/test123
# ./cwdtest
getcwd failed!!!
# pwd
/localfs/test123
#
 [2007-10-01 23:41 UTC] ab5602 at wayne dot edu
Wow, this is strange.  I'm very much closer to seeing what is going on with PHP+Solaris that is causing the issue here Ian.  I've tested pwd/getcwd() with every combination I could think of and this is how Solaris feels about permissions:

If you are not root AND you want to get your current working directory that has parents with exclusively 'x' permissions, you must do one of two things:

    a) Execute a getuid() program that is suid-root.

       OR: And this is the strange one...

    b) Tell Solaris that you already know where you are!!

If it is feasible, I'll see if I can come up with a patch to implement (b) if your architecture is Solaris and send it to the PHP internals list.  See below for how this works:

-----
# uname -a
SunOS opteron 5.10 Generic_118855-14 i86pc i386 i86pc
# pwd
/
# find ./dirtest/ -ls
449393    1 d--x--x--x   3 root     root          512 Oct  1 19:29 ./dirtest/
449394    1 d--x--x--x   2 root     root          512 Oct  1 19:29 ./dirtest/dirtest2
# cd /dirtest/dirtest2
# pwd
/dirtest/dirtest2
# su nobody
# pwd
cannot determine current directory
# cd /dirtest/dirtest2/
# pwd
/dirtest/dirtest2
#
 [2007-10-01 23:53 UTC] ab5602 at wayne dot edu
correction: a) Execute a program that implements getcwd() that is suid-root.
 [2007-10-02 06:54 UTC] ab5602 at wayne dot edu
I figured out what the issue was with the NFS shares and the "permission denied error" in our Solaris environment.  It was related to the same (--x) permission issue that you are having.

As it turns out, if you mount an NFS share in:

/mylocaldir/nfsmount/

The /nfsmount/ directory permissions, *before* you mount the share, need to be (r-x) or better, even though these permissions are hidden after the mount in order to avoid the Solaris+PHP include() bug.  Now include() and getcwd() work just fine!

It is very clear that this all goes back to two options:

1) Either make all the subdirs underneath (r-x)
   
   OR

2) If it is possible (which I'm not yet sure of), the PHP binary needs to "tell" Solaris that it already knows the current path by doing a chdir(/absolute/path/) or the like before trying getcwd() in order to make the "include() cause permission denied error" go away.
 [2007-10-02 11:11 UTC] jani@php.net
So this is only an issue with NFS shares? If so, please indicate that in the summary.
 [2007-10-05 03:29 UTC] ab5602 at wayne dot edu
No, the above NFS issues is a side-effect of:

1) Solaris getcwd() not functioning properly with (--x) directories

   and

2) PHP not properly allowing relative include()'s when #1 is the case

#2 is probably solvable w/ a bug fix, #1 is obviously not.
 [2007-10-05 11:58 UTC] jh at webteam dot at
Could reproduce this bug under Mac OS X 10.4.10 and PHP 5.2.4 (via 
MacPorts).
 [2007-10-05 22:01 UTC] ab5602 at wayne dot edu
I created the following patch which fixes the problem, however it still needs discussion as to if it is a good way to implement this fix.  At least it can serve as a starting point.  One concern was if this should be implemented at a lower level (TSRM code).

--- ./plain_wrapper.c.old       2007-10-05 02:50:59.000000000 -0400
+++ ./plain_wrapper.c   2007-10-05 02:55:38.000000000 -0400
@@ -885,9 +885,20 @@
                return NULL;
        }

-       if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) ==
NULL) {
-               return NULL;
-       }
+        if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL)
+                {
+                if (options & STREAM_OPEN_FOR_INCLUDE) {
+                        /* Attempt to open without path expansion anyways.
+                           Files in Solaris dirs with --x will
+                           not return a realpath, but are accessible */
+                        fd = open(filename, open_flags, 0666);
+                        if (fd != -1) {
+                                ret =
php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
+                                return ret; }
+                        else {
+                                return NULL; }
+                        }
+                }

        if (persistent) {
                spprintf(&persistent_id, 0, "streams_stdio_%d_%s",
open_flags, realpath);
 [2007-10-08 02:58 UTC] ab5602@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

This is fixed in CVS.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 23 09:02:23 2014 UTC