Bug #52312 [Com]: PHP lstat problem
| From: | v dot damore at gmail dot com | Date: | Tue, 13 Jul 2010 19:04:24 +0000 |
| Subject: | Bug #52312 [Com]: PHP lstat problem | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-152377@lists.php.net to get a copy of this message | ||
Edit report at http://bugs.php.net/bug.php?id=52312&edit=1
ID: 52312
Comment by: v dot damore at gmail dot com
Reported by: v dot damore at gmail dot com
Summary: PHP lstat problem
Status: Analyzed
Type: Bug
Package: Safe Mode/open_basedir
Operating System: Linux
PHP Version: 5.2.13
New Comment:
If you take a look at debugging done in
http://damore.xoom.it/apache-2.2_php-5.3.2_break-lstat.txt,
you can see
that tsrm_realpath_r is called in 2 different place:
- First during phar_find_in_include_path function
- Second during php_check_specific_open_basedir function.
* During php_check_specific_open_basedir, traverse entire path at least
three times, so i means 3 call to tsrm_realpath_r.
I don't discuss the need to traverse entire path, but only one time.
There should be a better way to implement such code, I'll try to write a
patch if there is someone that want help me looking what I'm writing.
Previous Comments:
------------------------------------------------------------------------
[2010-07-13 15:23:33] pajoye@php.net
The reason was due to a security flaw involving symbolic links and
realpath cache. It allowed to bypass open_basedir when a path was
cached. The cleanest way to fix it was to disable the realpath cache
when open_basedir/safemode are set.
Thanks Johannes to remind us about this change.
------------------------------------------------------------------------
[2010-07-13 11:01:23] v dot damore at gmail dot com
Looking at source code main/main.c of 5.2.13 I can see:
1292: /* Disable realpath cache if safe_mode or open_basedir are set
*/
if (PG(safe_mode) || (PG(open_basedir) &&
*PG(open_basedir))) {
CWDG(realpath_cache_size_limit) = 0;
}
1769: /* Disable realpath cache if safe_mode or open_basedir are set */
if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
CWDG(realpath_cache_size_limit) = 0;
}
So realpath cache is definitely disabled in case of safe_mode or
open_basedir.
This dramatically reduce performance of PHP Engine and this behavior can
bring a
server to its knees.
Especially because there is a lack of documentation!
Can you explain why this choose?
Must I continue debugging PHP engine in order to understand what's
happening?
------------------------------------------------------------------------
[2010-07-13 01:52:37] v dot damore at gmail dot com
I found where the problem is, this behavior is not a bug.
Looking at main/main.c I found following lines:
1416: /* Disable realpath cache if safe_mode or open_basedir
are set */
if (PG(safe_mode) || (PG(open_basedir) &&
*PG(open_basedir))) {
CWDG(realpath_cache_size_limit) = 0;
}
1978: /* Disable realpath cache if safe_mode or open_basedir are set */
if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
CWDG(realpath_cache_size_limit) = 0;
}
Could you explain why if safe_mode or open_basedir are set realpath
cache is disabled?
------------------------------------------------------------------------
[2010-07-13 01:38:26] v dot damore at gmail dot com
There is a interesting update, I have found CWDG define so now we have:
(gdb) print cwd_globals.realpath_cache_size_limit
$3 = 0
Probably you should check why realpath_cache_size_limit is equal to 0
------------------------------------------------------------------------
[2010-07-13 01:30:24] v dot damore at gmail dot com
After having set breakpoint tsrm_realpath_r and I have execute step by
step debug.
I think is interesting that after execution tsrm_virtual_cwd.c of line
681 execution continue on line 890.
gdb) break tsrm_realpath_r
Breakpoint 1 at 0x2b0b3c9f2702: file
/usr/local/sitipersonali/sitipersonali01/NSP_SERVICE/strillo/sources/php-5.3.2/TSRM/tsrm_virtual_cwd.c,
line 611.
(gdb) continue
Continuing.
Breakpoint 1, tsrm_realpath_r (path=0x7fffddfb32b0
"/usr/local/myspace/webspace/httpdocs/test.php", start=1, len=45,
ll=0x7fffddfb32ac, t=0x7fffddfb32a0, use_realpath=2, is_dir=0,
link_is_dir=0x0)
at
/usr/local/sitipersonali/sitipersonali01/NSP_SERVICE/strillo/sources/php-5.3.2/TSRM/tsrm_virtual_cwd.c:611
611 int directory = 0;
(gdb) step
624 if (len <= start) {
(gdb) step
628 i = len;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
630 i--;
(gdb) step
629 while (i > start && !IS_SLASH(path[i-1])) {
(gdb) step
633 if (i == len ||
(gdb) step
639 } else if (i == len - 2 && path[i] == '.' && path[i+1] ==
'.') {
(gdb) step
677 path[len] = 0;
(gdb) step
679 save = (use_realpath != CWD_EXPAND);
(gdb) step
681 if (start && save && CWDG(realpath_cache_size_limit)) {
(gdb) watch save
Hardware watchpoint 2: save
(gdb) print save
$1 = 1
(gdb) print start
$2 = 1
(gdb) print realpath_cache_size_limit
No symbol "realpath_cache_size_limit" in current context.
(gdb) step
890 if (save && lstat(path, &st) < 0) {
(gdb)
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/bug.php?id=52312
--
Edit this bug report at http://bugs.php.net/bug.php?id=52312&edit=1