php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72140 segfault after calling ERR_free_strings()
Submitted: 2016-05-03 08:34 UTC Modified: 2016-06-08 17:39 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: mpasinski at gmail dot com Assigned: bukka
Status: Closed Package: OpenSSL related
PHP Version: 5.6.21 OS: Linux
Private report: No CVE-ID:
 [2016-05-03 08:34 UTC] mpasinski at gmail dot com
Description:
------------
When using OpenSSL and CURL together PHP crashes after calling ERR_free_strings(). 

After running Apache in debug mode without forks (gdb --args httpd -X) you can see following backtraces:

#0  ERR_free_strings () at err.c:697
#1  0x00007fffe62cf658 in Curl_ossl_cleanup ()
   from libcurl.so.4
#2  0x00007fffe62d2e22 in Curl_ssl_cleanup ()
   from libcurl.so.4
#3  0x00007fffe62b12f5 in curl_global_cleanup ()
   from libcurl.so.4
#4  0x00007fffe5a13a98 in zm_shutdown_curl (type=<value optimized out>, 
    module_number=29)
    at php-5.6.21/ext/curl/interface.c:1263
#5  0x00007fffee359575 in module_destructor (module=0x7bf100)
    at php-5.6.21/Zend/zend_API.c:2376
#6  0x00007fffee3604a6 in i_zend_hash_bucket_delete (ht=0x7fffeead5de0, 
    p=0x7bf0a0)
    at php-5.6.21/Zend/zend_hash.c:182
#7  zend_hash_bucket_delete (ht=0x7fffeead5de0, p=0x7bf0a0)
    at php-5.6.21/Zend/zend_hash.c:192
#8  0x00007fffee360778 in zend_hash_graceful_reverse_destroy (
    ht=0x7fffeead5de0)
    at php-5.6.21/Zend/zend_hash.c:613
#9  0x00007fffee353a72 in zend_shutdown ()
    at php-5.6.21/Zend/zend.c:836
#10 0x00007fffee2f20ca in php_module_shutdown ()
    at php-5.6.21/main/main.c:2477
#11 0x00007fffee2f2179 in php_module_shutdown_wrapper (
    sapi_globals=<value optimized out>)
    at php-5.6.21/main/main.c:2445
#12 0x00007fffee3f7af1 in php_apache_child_shutdown (tmp=<value optimized out>)
    at php-5.6.21/sapi/apache2handler/sapi_apache2.c:398
#13 0x00007ffff7534b6e in run_cleanups (pool=0x918f88)
    at memory/unix/apr_pools.c:2352
#14 apr_pool_destroy (pool=0x918f88) at memory/unix/apr_pools.c:814
#15 0x000000000046b8fe in clean_child_exit (code=0) at prefork.c:227
#16 0x000000000046bdfb in child_main (child_num_arg=<value optimized out>, 
    child_bucket=<value optimized out>) at prefork.c:744
#17 0x000000000046c239 in make_child (s=0x6c6618, slot=0, bucket=0)
    at prefork.c:767
#18 0x000000000046d1db in prefork_run (_pconf=<value optimized out>, 
    plog=0x6c8378, s=0x6c6618) at prefork.c:979
#19 0x000000000043246e in ap_run_mpm (pconf=0x69b138, plog=0x6c8378, 
    s=0x6c6618) at mpm_common.c:96
#20 0x000000000042c4c4 in main (argc=2, argv=0x7fffffffe4b8) at main.c:778

So far everything works well, but then ERR_free_strings() is hit for the second time, followed by crash (this time OpenSSL cleanup is performed, after CURL cleanup was done above):

#0  0x00007eff7d6905f9 in ?? ()
#1  0x00007eff8021632f in CRYPTO_lock (mode=9, type=1, file=0x7eff8030a4bb "err.c", line=375)
    at cryptlib.c:596
#2  0x00007eff80285fd8 in int_err_del () at err.c:375
#3  ERR_free_strings () at err.c:697
#4  0x00007fffe53b853d in zm_shutdown_openssl (type=<value optimized out>, 
    module_number=31)
    at php-5.6.21/ext/openssl/openssl.c:1281
#5  0x00007fffee359575 in module_destructor (module=0x7c6000)
    at php-5.6.21/Zend/zend_API.c:2376
#6  0x00007fffee3604a6 in i_zend_hash_bucket_delete (ht=0x7fffeead5de0, 
    p=0x7c5fa0)
    at php-5.6.21/Zend/zend_hash.c:182
#7  zend_hash_bucket_delete (ht=0x7fffeead5de0, p=0x7c5fa0)
    at php-5.6.21/Zend/zend_hash.c:192
#8  0x00007fffee360778 in zend_hash_graceful_reverse_destroy (
    ht=0x7fffeead5de0)
    at php-5.6.21/Zend/zend_hash.c:613
#9  0x00007fffee353a72 in zend_shutdown ()
    at php-5.6.21/Zend/zend.c:836
#10  0x00007fffee2f20ca in php_module_shutdown ()
    at php-5.6.21/main/main.c:2477
#11  0x00007fffee2f2179 in php_module_shutdown_wrapper (
    sapi_globals=<value optimized out>)
    at php-5.6.21/main/main.c:2445
#12  0x00007fffee3f7af1 in php_apache_child_shutdown (tmp=<value optimized out>)
    at php-5.6.21/sapi/apache2handler/sapi_apache2.c:398
#13 0x00007ffff7534b6e in run_cleanups (pool=0x918f88)
    at memory/unix/apr_pools.c:2352
#14 apr_pool_destroy (pool=0x918f88) at memory/unix/apr_pools.c:814
#15 0x000000000046b8fe in clean_child_exit (code=0) at prefork.c:227
#16 0x000000000046bdfb in child_main (child_num_arg=<value optimized out>, 
    child_bucket=<value optimized out>) at prefork.c:744
#17 0x000000000046c239 in make_child (s=0x6c6618, slot=0, bucket=0)
    at prefork.c:767
#18 0x000000000046d1db in prefork_run (_pconf=<value optimized out>, 
    plog=0x6c8378, s=0x6c6618) at prefork.c:979
#19 0x000000000043246e in ap_run_mpm (pconf=0x69b138, plog=0x6c8378, 
    s=0x6c6618) at mpm_common.c:96
#20 0x000000000042c4c4 in main (argc=2, argv=0x7fffffffe4b8) at main.c:778

It looks like it is legal to call ERR_free_strings() once, whereas while using OpenSSL and CURL this code is called twice.


All versions since 5.6.19 are affected. The commit causing the issue is:

commit a63d0f55da87fc620c66f1b909d752d7c8b1159c
Author: Jakub Zelenka <bukka@php.net>
Date:   Mon Jan 25 17:50:16 2016

    Fix memory leak with not freeing OpenSSL errors






Patches

Revert-Fix-memory-leak-with-not-freeing-OpenSSL-erro.patch (last revision 2016-05-03 08:37 UTC) by mpasinski at gmail dot com)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-03 10:22 UTC] ab@php.net
-Assigned To: +Assigned To: bukka
 [2016-06-03 10:22 UTC] ab@php.net
Jakub, could you please take a look at this?

Thanks.
 [2016-06-05 13:26 UTC] bukka@php.net
There shouldn't be a problem with calling ERR_free_strings multiple times as you can see in OpenSSL code:

https://github.com/openssl/openssl/blob/ae5c8664e587f2445c8e4eb436cffbb64af4f6b8/crypto/err/err.c#L376

The problem that I see from the backtrace is due to calling the locking function:

https://github.com/openssl/openssl/blob/ae5c8664e587f2445c8e4eb436cffbb64af4f6b8/crypto/cryptlib.c#L596

It could be because some ext set locking callback and then it got unloaded without resetting it. Could you try the patch below if it fixes your issue?


diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 88e396c..aeaeeec 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1278,6 +1278,7 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
        EVP_cleanup();
 
 #if OPENSSL_VERSION_NUMBER >= 0x00090805f
+       CRYPTO_set_locking_callback(NULL);
        ERR_free_strings();
 #endif
 [2016-06-05 13:59 UTC] bukka@php.net
If you prefer an actual patch for git apply, you can use:

https://github.com/bukka/php-src/commit/d550131d7eda2c111e5f4cf192bd1d3f58b075b0.patch
 [2016-06-08 14:20 UTC] mpasinski at gmail dot com
Thanks for taking care of this one. I did some tests and can confirm that this fixes the issue.
 [2016-06-08 17:34 UTC] bukka@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05033c9ebd015baf825581e5725a594da277d560
Log: Fix bug #72140 (segfault after calling ERR_free_strings())
 [2016-06-08 17:34 UTC] bukka@php.net
-Status: Assigned +Status: Closed
 [2016-06-08 17:37 UTC] bukka@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05033c9ebd015baf825581e5725a594da277d560
Log: Fix bug #72140 (segfault after calling ERR_free_strings())
 [2016-06-08 17:37 UTC] bukka@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05033c9ebd015baf825581e5725a594da277d560
Log: Fix bug #72140 (segfault after calling ERR_free_strings())
 [2016-06-08 17:39 UTC] bukka@php.net
Thanks for testing. It's been merged.
 [2016-06-21 07:26 UTC] stas@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05033c9ebd015baf825581e5725a594da277d560
Log: Fix bug #72140 (segfault after calling ERR_free_strings())
 [2016-06-22 05:58 UTC] krakjoe@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05033c9ebd015baf825581e5725a594da277d560
Log: Fix bug #72140 (segfault after calling ERR_free_strings())
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC