PHP安全模式/ open_basedir – lstat性能问题

在读取文件之前,PHP多次查看完整path。 而这种情况发生时,在Apache HTTPDconfiguration指定PHP_ADMIN_VALUE open_basedir设置或如果safe_mode是ON

如果我有一个简单的网站只有phpinfo.php页面,里面我们只有“”。

考虑我们有最新版本的httpd(2.2.15)和PHP(5.2.13或5.3.2)。

如果我们在虚拟主机configuration中指定safe_mode = on或PHP_ADMIN_VALUE open_basedir

 <目录“/ usr / local / myspace / webspace / httpdocs”>
                 PHP_ADMIN_VALUE open_basedir“/ usr / local / myspace / webspace”
 </目录>
 <VirtualHost *:80>
         ServerName damorealt.xoom.it
         DocumentRoot“/ usr / local / myspace / webspace / httpdocs”
     CustomLog / var / log / httpd / damorealt / access_log合并
     ErrorLog / var / log / httpd / damorealt / error_log
 </ VirtualHost>

调用页面http://damorealt.xoom.it/phpinfo.php我们可以重现以下行为:

首先检查

 25933 lstat(“/ usr”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0

第二次检查

 25933 lstat(“/ usr”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0

第三次检查(不完整)

 25933 lstat(“/ usr”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0

第五次检查。

 25933 lstat(“/ usr”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 25933 lstat(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0

阅读文件!

 25933 open(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,O_RDONLY)= 16
 25933 fstat(16,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0
 25933(16,“\ n”,8192)= 16
 25933阅读(16,“”,8192)= 0
 25933阅读(16,“”,8192)= 0
 25933closures(16)= 0

如果删除了PHP_ADMIN_VALUE open_basedir“/ usr / local / myspace / webspace” ::

首先检查

 26235 time(NULL)= 1278696735
 26235 lstat(“/ usr”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 26235 lstat(“/ usr / local”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 26235 lstat(“/ usr / local / myspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 26235 lstat(“/ usr / local / myspace / webspace”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 26235 lstat(“/ usr / local / myspace / webspace / httpdocs”,{st_mode = S_IFDIR | 0755,st_size = 4096,...})= 0
 26235 lstat(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0

阅读文件。

 26235 open(“/ usr / local / myspace / webspace / httpdocs / phpinfo.php”,O_RDONLY)= 16
 26235 fstat(16,{st_mode = S_IFREG | 0644,st_size = 16,...})= 0
 26235阅读(16,“\ n”,8192)= 16
 26235读(16,“”,8192)= 0
 26235读(16,“”,8192)= 0
 26235closures(16)= 0
 26235 uname({sys =“Linux”,node =“svilpar4”,...})= 0
 26235 time(NULL)= 1278696735
 26235 writev(15,[{“HTTP / 1.1 200 OK \ r \ ndate:星期五,09 J”...,173},[...]
 26235 chdir(“/”)= 0

有人可以解释为什么PHP有这样的行为?

如果设置了safe_mode或open_basedir,则实际pathcaching将被禁用 。 这大大降低了PHP引擎的性能,这种行为可能会使服务器瘫痪。 特别是因为缺less文档!

看看PHP引擎5.2.13的源代码main / main.c,你可以看到:

 1292:/ *如果设置了safe_mode或open_basedir,则禁用实际pathcaching 
 * /
                如果(PG(safe_mode)||(PG(open_basedir)&& * PG(open_basedir))){
                         CWDG(realpath_cache_size_limit)= 0;
                 }

 1769:/ *如果设置了safe_mode或open_basedir,则禁用实际pathcaching* /
        如果(PG(safe_mode)||(PG(open_basedir)&& * PG(open_basedir))){
                 CWDG(realpath_cache_size_limit)= 0;
         }

请参阅: http : //bugs.php.net/bug.php?id=52312