Bug #68486 [Com]: PHP SegFault zend_hash_find
| From: | php at bof dot de | Date: | Tue, 17 Mar 2015 16:42:25 +0000 |
| Subject: | Bug #68486 [Com]: PHP SegFault zend_hash_find | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-191435@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68486&edit=1
ID: 68486
Comment by: php at bof dot de
Reported by: wattwood at tcstire dot com
Summary: PHP SegFault zend_hash_find
Status: Open
Type: Bug
Package: Apache2 related
Operating System: Ubuntu 14.04.1 LTS
PHP Version: 5.5.19
Block user comment: N
Private report: N
New Comment:
ab@php.net : regarding reproducing the issue you can take any PHP script, a simple one-line echo is
sufficient, and then request it twice using the echo|netcat command as shown in several of the
comments here.
Previous Comments:
------------------------------------------------------------------------
[2015-03-17 16:38:32] php at bof dot de
Sorry for the broken gist patches. Apparently gists do funny things with whitespace... I should have
tested that, but didn't.
To make things easy I put the patches up on my personal webspace. Please don't link to that in
any blog posts or stuff like that :)
Same patch as in the last gist, without and with added debug/trace calls:
http://bei.bof.de/php/sapi_apache2.noreentry.v2.patch
http://bei.bof.de/php/sapi_apache2.noreentry.debug.v2.patch
Since then I also added something alluded to on internals in a new thread "PHP apache2handler
virtual() function" - now implemented with a new PHP function apache_tail_request(). This can
be found, on top of the changes of the v2 patch, in these patches:
http://bei.bof.de/php/sapi_apache2.noreentry.v3.patch
http://bei.bof.de/php/sapi_apache2.noreentry.debug.v3.patch
All patches were made on top of PHP 5.6.7RC1, checked out by tag from git.
For about 2 hours now, I have the v3 patch actively running on one of my production servers, under
apache 2.4 now, and without any coredumps / segvs in the logs or any kind of performance regression.
This is with some 80 requests per second, so it gets a good workout. The patch appears to work.
------------------------------------------------------------------------
[2015-03-16 19:11:22] gmoniker at gmail dot com
This is some great work.
One remark, the php_functions.c file of the apache2handler inside the virtual definition mentions
that the ap_rflush is supposed to be a workaround for
http://issues.apache.org/bugzilla/show_bug.cgi?id=17629.
Fortunately reading its comments seems to indicate that the underlying problem was solved in Apache
2.2 around august 2010 with https://svn.apache.org/viewvc?view=revision&revision=988400.
------------------------------------------------------------------------
[2015-03-16 14:11:00] ab@php.net
Patrick,
somehow the latest patch is broken, it won't apply to any of 5.5 through master. Also, is there
any piece of code to be used for the tests?
Thanks.
------------------------------------------------------------------------
[2015-03-15 10:17:28] php at bof dot de
Reworked the patch another round, see updated gist:
https://gist.github.com/bof/15173c7a11cb12a7b96f
The pool cleanup logic is reworked, with the goal of never cleaning up the
SG(server_context) of something other than the currently running + not yet complete request -
regardless of when and how delayed a pool cleanup callback comes in. This I do by 1) adding a
ctx->server_context pointer to the context structure, 2) registering ctx instead of
&SG(server_context) with the pool cleanup callback, and finally 3) in
php_server_context_cleanup() I check that *ctx->server_context == ctx, and only in that case I
NULL it.
I also rearranged the php_handler() config handling a bit, so that the xbithack-during-reentry case
should now be correct, too; and there's some all-around cleanup.
The debug output of the previous patch is gone (available on request).
I tested this patch, lightly, with my testcases and our normal codebase, under both Apache 2.4.12,
the openSUSE 13.1 Apache 2.4.6, and an older Apache 2.2 setup as I use it in normal production so
far. No issues were found, the new logic seems to work the same everywhere. I also ran the apache
2.4.12 variant under valgrind, also without any issues flagged.
THIS STILL NEEDS REVIEW from somebody who previously worked on the apache2handler code. But I think
it's solid enough now, and I'll probably test it in production on monday
------------------------------------------------------------------------
[2015-03-14 10:34:07] php at bof dot de
Here's a gist with a patch, against 5.6.7RC1, that appears to fix the issue for me, at least
for the things I tested.
https://gist.github.com/bof/15173c7a11cb12a7b96f
(patch contains lots of extra debug output, none of the ap_log_error calls I added would be good for
merging)
I basically rip out the whole parent_req handling attempts in php_handler(), and make
ctx->request_processed be the only indicator regarding reentrancy to the interpreter. In case
such a reentrancy is attempted, I error out early in php_handler() before any manipulation to
interpreter state is done.
The PHP virtual() function (provided in php_functions.c) will now cleanly fail when used to
"embed" another PHP script (the worst reentrancy), but it continues to work when embedding
an URI handled by any other handler (the not_for_us case).
While testing I had a final issue with the ap_rflush() call in virtual() resulting in pool
destruction of the in-flight request, due to the apache 2.4 EOR thing gmoniker mentioned in the
previous comment. If anybody is curious, drop me an email, I've got the backtrace saved. For
now I have disabled that ap_rflush() call in virtual(), and I don't know what could break by
that.
Anyway, after some light testing with this gist's patch applied, my own codebase keeps working
normally, and the double-echo test now works without crashes for any of these cases:
- two normal PHP requests in a row
- two PHP requests in a row, each using virtual to embed another PHP script (embedded script NOT
run, PHP warning message in virtual() caller)
- two PHP requests in a row, using virtual to embed a non-PHP thing (/robots.txt tested...) - works
as it should.
------------------------------------------------------------------------
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
https://bugs.php.net/bug.php?id=68486
--
Edit this bug report at https://bugs.php.net/bug.php?id=68486&edit=1