php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63595 GMP memory management conflicts with other libraries using GMP
Submitted: 2012-11-24 10:15 UTC Modified: 2014-10-27 06:40 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: arekm at maven dot pl Assigned: remi
Status: Closed Package: GNU MP related
PHP Version: 5.3.19 OS:
Private report: No CVE-ID:
 [2012-11-24 10:15 UTC] arekm at maven dot pl
Description:
------------
php gmp module uses:

mp_set_memory_functions(gmp_emalloc, gmp_erealloc, gmp_efree);

to switch to Zend memory management functions.

The problem is that there are other modules that use gmp. One is php-curl in 
case when curl uses gnutls for SSL connections (gnutls >= 3.1.1).

gnutls also uses gmp.

The problem happens when curl first uses gmp, gmp allocates some things (using 
generic memory management functions) and then php-gmp module changes memory 
management functions to own (Zend) one.

Then memory allocated by generic functions is going to be reallocated/freed 
using Zend functions which causes segfault.

Probably the solution would be to immediately set
mp_set_memory_functions
to Zend functions, before any other module has a chance to initialize gmp.

More:
http://lists.gnu.org/archive/html/help-gnutls/2012-11/msg00050.html
http://lists.gnu.org/archive/html/help-gnutls/2012-11/msg00049.html

Test script:
---------------
- build php with curl and gmp
- libcurl library needs to be built with gnutls >= 3.1.1
- run php cli
- press ctrl+D
=> result = segfault

Expected result:
----------------
No segfault.

Actual result:
--------------
Segfault.

Program received signal SIGSEGV, Segmentation fault.
0x00007fffea23ef20 in ?? ()
(gdb) bt
#0  0x00007fffea23ef20 in ?? ()
#1  0x00007fffeb445d3b in mp_clear_multi (address@hidden) at multi.c:38
#2  0x00007fffeb4472ca in ecc_del_point (p=0xc63ed0) at ecc_points.c:62
#3  0x00007fffeb446972 in _ecc_wmnaf_cache_entry_free (p=<optimized out>) at 
ecc_mulmod_cached.c:54
#4  ecc_wmnaf_cache_free () at ecc_mulmod_cached.c:68
#5  0x00007fffeb445685 in gnutls_crypto_deinit () at init.c:44
#6  0x00007fffeb3adb71 in gnutls_global_deinit () at gnutls_global.c:305
#7  0x00007fffee0c9a79 in Curl_gtls_cleanup () at gtls.c:182
#8  0x00007fffee0ca189 in Curl_ssl_cleanup () at sslgen.c:193
#9  0x00007fffee0bbbf5 in curl_global_cleanup () at easy.c:325
#10 0x00007fffee6f9bf8 in zm_shutdown_curl () from /usr/lib64/php/curl.so
#11 0x00007ffff7a96105 in module_destructor () from 
/usr/lib64/libphp_common-5.3.18.so
#12 0x00007ffff7a9b4ae in ?? () from /usr/lib64/libphp_common-5.3.18.so
#13 0x00007ffff7a9cd08 in zend_hash_graceful_reverse_destroy () from 
/usr/lib64/libphp_common-5.3.18.so
#14 0x00007ffff7a8f175 in zend_shutdown () from 
/usr/lib64/libphp_common-5.3.18.so
#15 0x00007ffff7a3e01b in php_module_shutdown () from 
/usr/lib64/libphp_common-5.3.18.so
#16 0x0000000000403406 in main ()
(gdb)

Patches

gmp-memory.patch (last revision 2014-10-11 06:50 UTC) by remi@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-10-10 08:30 UTC] remi@php.net
Some other cases:

Apache HTTP + mod_php + mod_gnutls => segfaults

PHP + odbc + freetds (use gnutls) => segfaults
 [2014-10-10 08:39 UTC] remi@php.net
Another backtrace (php + odbc + freetds)

(gdb) bt
#0  0x0000555555798a78 in _zend_mm_free_int ()
#1  0x00007fffe6ace02a in mp_clear_multi () from /lib64/libgnutls.so.28
#2  0x00007fffe6acf64a in ecc_del_point () from /lib64/libgnutls.so.28
#3  0x00007fffe6acec9a in ecc_wmnaf_cache_free () from /lib64/libgnutls.so.28
#4  0x00007fffe6a382c1 in gnutls_global_deinit () from /lib64/libgnutls.so.28
#5  0x00007ffff7debb7a in _dl_fini () from /lib64/ld-linux-x86-64.so.2
#6  0x00007ffff472be59 in __run_exit_handlers () from /lib64/libc.so.6
#7  0x00007ffff472bea5 in exit () from /lib64/libc.so.6
#8  0x0000555555619ffa in main ()
 [2014-10-10 16:55 UTC] stas@php.net
-Summary: Not really sane memory management initialization +Summary: GMP memory management conflicts with other libraries using GMP
 [2014-10-10 23:43 UTC] rasmus@php.net
ext/gmp calls mp_set_memory_functions() in the MINIT hook so it should be fine for any PHP extensions that might use it. I don't see how a curl ssl call from PHP would end up having a problem. However, I can see the cases Remi mentioned where non-php things like mod_gnutls gets in the mix. Might have to set it back in RSHUTDOWN, but I would hate having to do that. Anything in the per-request hooks end up getting called on every request regardless of whether anything used anything from gmp on that request.

The other option would be to yank it from MINIT and do it for every gmp operation/object.
 [2014-10-11 06:16 UTC] remi@php.net
The following patch has been added/updated:

Patch Name: gmp-memory.patch
Revision:   1413008196
URL:        https://bugs.php.net/patch-display.php?bug=63595&patch=gmp-memory.patch&revision=1413008196
 [2014-10-11 06:50 UTC] remi@php.net
The following patch has been added/updated:

Patch Name: gmp-memory.patch
Revision:   1413010232
URL:        https://bugs.php.net/patch-display.php?bug=63595&patch=gmp-memory.patch&revision=1413010232
 [2014-10-11 09:51 UTC] nikic@php.net
Before going with ugly solutions like switching the allocator in every single function, could we please try the approach of

a) resetting memory allocators in MSHUTDOWN
b) setting memory allocators in RINIT and resetting in RSHUTDOWN.

I'd much prefer this to happen on every request regardless of GMP usage than for every single GMP function call.
 [2014-10-14 07:30 UTC] remi@php.net
Problem with having the PHP allocator set globally during all the request, is that it will be used by other libraries (ex freetds or zarafa/mapi), and then the free (during exit /  gnutls_global_deinit) will segfault:
- using php efree as the php memory allocator is already shutdown
- using standard free as the php was not allocated using malloc
 [2014-10-18 08:06 UTC] stas@php.net
The big problem is that nobody guarantees us gnutls GMP object lifetimes would match PHP request lifetime. They could allocate something outside the request and free inside, or vice versa.
 [2014-10-27 06:40 UTC] remi@php.net
-Assigned To: +Assigned To: remi
 [2014-10-27 06:54 UTC] remi@php.net
Automatic comment on behalf of remi
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3c925b18fa96043e5d7e86f9ce544b143c3c2079
Log: Fix bug #63595 GMP memory management conflicts with other libraries using GMP
 [2014-10-27 06:54 UTC] remi@php.net
-Status: Assigned +Status: Closed
 [2014-11-03 19:44 UTC] stas@php.net
Automatic comment on behalf of remi
Revision: http://git.php.net/?p=php-src.git;a=commit;h=7740edae36fea4e831afc6f1e37eb559dcf597f0
Log: Fix bug #63595 GMP memory management conflicts with other libraries using GMP
 [2014-11-18 20:34 UTC] ab@php.net
Automatic comment on behalf of remi
Revision: http://git.php.net/?p=php-src.git;a=commit;h=7740edae36fea4e831afc6f1e37eb559dcf597f0
Log: Fix bug #63595 GMP memory management conflicts with other libraries using GMP
 [2014-11-18 20:34 UTC] ab@php.net
Automatic comment on behalf of remi
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3c925b18fa96043e5d7e86f9ce544b143c3c2079
Log: Fix bug #63595 GMP memory management conflicts with other libraries using GMP
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Feb 26 14:01:37 2017 UTC