php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66036 Crash on SIGTERM in apache process
Submitted: 2013-11-05 18:19 UTC Modified: 2014-09-01 21:46 UTC
From: cbrichford+phpbugs at appdynamics dot com Assigned: keyur
Status: Closed Package: Scripting Engine problem
PHP Version: Irrelevant OS: CentOS 5.5
Private report: No CVE-ID:
 [2013-11-05 18:19 UTC] cbrichford+phpbugs at appdynamics dot com
Description:
------------
The automated tests for the product I work on send SIGTERM to the root process of an apache process pool.  Apache in turn sends SIGTERM to each worker.  If an apache worker process happens to be in the middle of running a PHP request when it receives SIGTERM it will reliably core dump if the php program contains a subclass of a class defined in an extension ( an internal class ) and that internal class defines a static constant.

The class entry for the internal class contains a zval allocated with malloc ( not emalloc ) for each static constant defined in the class.  When a subclass of the internal class is created by a php program the zval for each static constant has its refcount incremented by one and is referenced by the class entry for the subclass.

During shutdown the last class entry to decrement the refcount of the zval for each static constant determines whether or not the zval will be free'd with free or efree.  If the internal class is destroyed before the subclass then the internal class will decrement the refcount of the zval for each static constant by 1, but not call free.  Then the subclass will start its destruction sequence which detect that it is the last reference to the zval for each static constant and will then try to free the zval with efree.

The result of all of this a buffer that was allocated with malloc is passed to efree.

This bug is present in PHP 5.3.27 and PHP 5.5.4.



Test script:
---------------
<?php

# Subclass an internal class that has a static constant.
class MyArrayObject extends ArrayObject
{
    public function __construct()
    {
        parent::__construct();
    }
}

$pid = getmypid();

$cmd = "kill -TERM " . $pid;

# commit suicide so we know that we receive SIGTERM while running php code.
shell_exec($cmd);

while(true)
    sleep(1);


Expected result:
----------------
No core dump.

Actual result:
--------------
Here is stack trace from PHP 5.5.4:

Core was generated by `/usr/sbin/httpd'.
Program terminated with signal 11, Segmentation fault.
#0  _zend_mm_free_int (heap=0x2b35d0a92f90, p=0x2b35c49f40b0) at /home/cbrichford/git/github/php-src/Zend/zend_alloc.c:2104
2104		if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
(gdb) where
#0  _zend_mm_free_int (heap=0x2b35d0a92f90, p=0x2b35c49f40b0) at /home/cbrichford/git/github/php-src/Zend/zend_alloc.c:2104
#1  0x00002b35cf3d8dcb in zend_hash_destroy (ht=0x2b35d1f66768) at /home/cbrichford/git/github/php-src/Zend/zend_hash.c:560
#2  0x00002b35cf3c1ca8 in destroy_zend_class (pce=<value optimized out>) at /home/cbrichford/git/github/php-src/Zend/zend_opcode.c:301
#3  0x00002b35cf3d8dcb in zend_hash_destroy (ht=0x2b35d1ef53f0) at /home/cbrichford/git/github/php-src/Zend/zend_hash.c:560
#4  0x00002b35cf3cc04d in zend_shutdown () at /home/cbrichford/git/github/php-src/Zend/zend.c:824
#5  0x00002b35cf36ccda in php_module_shutdown () at /home/cbrichford/git/github/php-src/main/main.c:2367
#6  0x00002b35cf36cd99 in php_module_shutdown_wrapper (sapi_globals=<value optimized out>) at /home/cbrichford/git/github/php-src/main/main.c:2335
#7  0x00002b35cf479a61 in php_apache_child_shutdown (tmp=<value optimized out>) at /home/cbrichford/git/github/php-src/sapi/apache2handler/sapi_apache2.c:398
#8  0x00002b35c5fb969d in run_cleanups (cref=0x2b35d203e5b8) at memory/unix/apr_pools.c:2097
#9  0x00002b35c5fb9cce in apr_pool_destroy (pool=0x2b35d203e598) at memory/unix/apr_pools.c:744
#10 0x00002b35c46fceee in ?? ()
#11 0x00002b35c46fcf1b in ?? ()
#12 <signal handler called>
#13 0x00002b35c66b3170 in __read_nocancel () from /lib64/libc.so.6
#14 0x00002b35cf389f26 in php_stdiop_read (stream=0x2b35d1f64fd0, buf=0x2b35d1f6b708 "\370\266\366\321\065+", count=8192) at /home/cbrichford/git/github/php-src/main/streams/plain_wrapper.c:349
#15 0x00002b35cf385424 in php_stream_fill_read_buffer (stream=0x2b35d1f64fd0, size=8192) at /home/cbrichford/git/github/php-src/main/streams/streams.c:692
#16 0x00002b35cf3855ca in _php_stream_read (stream=0x2b35d1f64fd0, buf=<value optimized out>, size=8192) at /home/cbrichford/git/github/php-src/main/streams/streams.c:735
#17 0x00002b35cf386541 in _php_stream_copy_to_mem (src=0x2b35d1f64fd0, buf=0x7fff6eb79068, maxlen=0, persistent=0) at /home/cbrichford/git/github/php-src/main/streams/streams.c:1466
#18 0x00002b35cf310f41 in zif_shell_exec (ht=<value optimized out>, return_value=0x2b35d1f65818, return_value_ptr=<value optimized out>, this_ptr=<value optimized out>,
    return_value_used=<value optimized out>) at /home/cbrichford/git/github/php-src/ext/standard/exec.c:459
#19 0x00002b35cf44d3e3 in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>) at /home/cbrichford/git/github/php-src/Zend/zend_vm_execute.h:550
#20 0x00002b35cf43e8f0 in execute_ex (execute_data=0x2b35d1f34160) at /home/cbrichford/git/github/php-src/Zend/zend_vm_execute.h:363
#21 0x00002b35cf3cadf9 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/cbrichford/git/github/php-src/Zend/zend.c:1318
#22 0x00002b35cf36cb19 in php_execute_script (primary_file=0x7fff6eb7b5e0) at /home/cbrichford/git/github/php-src/main/main.c:2489
#23 0x00002b35cf47ac0d in php_handler (r=0x2b35d2104b40) at /home/cbrichford/git/github/php-src/sapi/apache2handler/sapi_apache2.c:667
#24 0x00002b35c46eae8a in ap_run_handler ()
#25 0x00002b35c46ee318 in ap_invoke_handler ()
#26 0x00002b35c46f8e28 in ap_process_request ()
#27 0x00002b35c46f6010 in ?? ()
#28 0x00002b35c46f2112 in ap_run_process_connection ()
#29 0x00002b35c46fd2c9 in ?? ()
#30 0x00002b35c46fd55a in ?? ()
#31 0x00002b35c46fd610 in ?? ()
#32 0x00002b35c46fe2fb in ap_mpm_run ()
#33 0x00002b35c46d7fd8 in main ()
(gdb)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-11-06 17:24 UTC] cbrichford+phpbugs at appdynamics dot com
-Package: Apache2 related +Package: Scripting Engine problem
 [2013-11-06 17:24 UTC] cbrichford+phpbugs at appdynamics dot com
Since this issue is not really specific to apache, I'm changing the package to "Scripting Engine Problem".  This bug can happen any time zend_shutdown is called between during a call to zend_execute_scripts.
 [2013-11-06 17:27 UTC] cbrichford+phpbugs at appdynamics dot com
There is reason to believe this bug only happens when zts is disabled.  When zts is enabled static constants of internal classes have their zvals copied to the derived classes instead of having the derived class increment the refcount on the zval from the internal base class.
 [2013-11-06 17:30 UTC] rasmus@php.net
Related to bug #65463 I think

We need to have another look at the shutdown order here
 [2014-09-01 21:46 UTC] keyur@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: keyur
 [2014-09-01 21:46 UTC] keyur@php.net
The fix for this bug has been committed.

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/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.

Fix merged: https://github.com/php/php-src/commit/197095c29ecd643a9d8c8187fa9e87a6d92ceacd
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Thu Jul 27 16:01:43 2017 UTC