php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #36152 problems with curl+ssl and pgsql+ssl in same PHP
Submitted: 2006-01-25 09:12 UTC Modified: 2006-01-26 14:48 UTC
From: misiek at dione dot ids dot pl Assigned: mike
Status: Closed Package: cURL related
PHP Version: 5CVS, 4CVS (2006-01-25) (snap) OS: *
Private report: No CVE-ID:
 [2006-01-25 09:12 UTC] misiek at dione dot ids dot pl
Description:
------------
php5.1-200601242130
./configure --prefix=/tmp/qq --enable-maintainer-zts --with-pgsql=shared,/usr --with-curl=shared,/usr

postgresql client libs 8.1.2 (compiled with --enable-thread-safety and --with-openssl)

curl 7.15.1 also compiled with openssl

[root@pepe 16112]# cat /tmp/qq/lib/php.ini
extension=curl.so
extension=pgsql.so

(note that extensions loading order matters)

The problems seems to be in thread safety locking code somewhere in openssl and this combination triggers it (now the bug could be in php curl module, pgsql client library, openssl... don't know yet).

Reproduce code:
---------------
[root@pepe 16112]# cat config.php
<?php

pg_connect("host='db01.agnat.pl' user='dfsdf' password='sfsf' dbname='sdfsdf'");

?>
[root@pepe 16112]# /tmp/qq/bin/php config.php
X-Powered-By: PHP/5.1.3-dev
Content-type: text/html

Memory fault


The host is important - there needs to be postgresql server  which accepts SSL connections (this one accepts only ssl connections). user/password/dbname doesn't matter.

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

Actual result:
--------------
Memory fault

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-01-25 10:21 UTC] misiek at dione dot ids dot pl
Now I'm testing php with ZTS disabled and it still segfaults, seems that's unrelated to thread safety.

(gdb) r
Starting program: /tmp/qq/bin/php config.php
X-Powered-By: PHP/5.1.3-dev
Content-type: text/html


Program received signal SIGSEGV, Segmentation fault.
0xb766b428 in ?? ()
(gdb) bt
#0  0xb766b428 in ?? ()
#1  0xb783187e in CRYPTO_lock (mode=9, type=1, file=0xb79023ad "err.c", line=354) at cryptlib.c:430
#2  0xb7896440 in int_err_del () at err.c:354
#3  0xb7896deb in ERR_free_strings () at err.c:651
#4  0xb79a9e43 in Curl_ossl_cleanup () at ssluse.c:569
#5  0xb79bc570 in Curl_ssl_cleanup () at sslgen.c:185
#6  0xb79b45a9 in curl_global_cleanup () at easy.c:269
#7  0xb7ef7efb in zm_shutdown_curl (type=1, module_number=21)
    at /home/users/arekm/php5.1-200601242130/ext/curl/interface.c:491
#8  0x0822f160 in module_destructor (module=0x8396d40) at /home/users/arekm/php5.1-200601242130/Zend/zend_API.c:1757
#9  0x08232b98 in zend_hash_apply_deleter (ht=0x8363c20, p=0x8396d10)
    at /home/users/arekm/php5.1-200601242130/Zend/zend_hash.c:574
#10 0x08232c3c in zend_hash_graceful_reverse_destroy (ht=0x8363c20)
    at /home/users/arekm/php5.1-200601242130/Zend/zend_hash.c:640
#11 0x0822a61e in zend_shutdown () at /home/users/arekm/php5.1-200601242130/Zend/zend.c:720
#12 0x081f26cf in php_module_shutdown () at /home/users/arekm/php5.1-200601242130/main/main.c:1604
#13 0x0828f732 in main (argc=2, argv=0xbfc153a4) at /home/users/arekm/php5.1-200601242130/sapi/cgi/cgi_main.c:1661
(gdb) frame 1
#1  0xb783187e in CRYPTO_lock (mode=9, type=1, file=0xb79023ad "err.c", line=354) at cryptlib.c:430
430                             locking_callback(mode,type,file,line);
(gdb) print locking_callback
$1 = (void (*)(int, int, const char *, int)) 0xb766b428
(gdb) print *locking_callback
Cannot access memory at address 0xb766b428
(gdb)    

something bad happens with callback function pointer (I guess it's callback set by libpg.so library)
 [2006-01-25 10:28 UTC] misiek at dione dot ids dot pl
[root@pepe 16112]# gdb --args /tmp/qq/bin/php config.php
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pld-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) b CRYPTO_set_locking_callback
Function "CRYPTO_set_locking_callback" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (CRYPTO_set_locking_callback) pending.
(gdb) b int_err_del
Function "int_err_del" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (int_err_del) pending.
(gdb) r
Starting program: /tmp/qq/bin/php config.php
Breakpoint 3 at 0xb78ee736: file cryptlib.c, line 349.
Pending breakpoint "CRYPTO_set_locking_callback" resolved
Breakpoint 4 at 0xb795341a: file err.c, line 354.
Pending breakpoint "int_err_del" resolved

Breakpoint 3, CRYPTO_set_locking_callback (func=0xb7728428 <pq_lockingcallback>) at cryptlib.c:349
349             locking_callback=func;
(gdb) print func
$1 = (void (*)(int, int, const char *, int)) 0xb7728428 <pq_lockingcallback>
(gdb) c
Continuing.
X-Powered-By: PHP/5.1.3-dev
Content-type: text/html


Breakpoint 4, int_err_del () at err.c:354
354             CRYPTO_w_lock(CRYPTO_LOCK_ERR);
(gdb) s
CRYPTO_lock (mode=9, type=1, file=0xb79bf3ad "err.c", line=354) at cryptlib.c:414
414             if (type < 0)
(gdb) n
429                     if (locking_callback != NULL)
(gdb) print locking_callback
$2 = (void (*)(int, int, const char *, int)) 0xb7728428.
(gdb) print *locking_callback
Cannot access memory at address 0xb7728428
(gdb)      

this trace shows that pq_lockingcallback() was lost somewhere and code issued from curl tries to use it (callback from pgsql).

Maybe openssl initialization and deinitialization should be somehow made once for all php modules that use openssl instead of doing per module init?
 [2006-01-25 10:42 UTC] misiek at dione dot ids dot pl
This also happens in php4.4.2.

openssl uses globals to store callbacks data which makes things complicated. libpq and curl allow to manage ssl lockig in application code (see PQregisterThreadLock() and PQinitSSL() for libpq) so doing ssl lock management in one place for all modules sounds like possible solution.
 [2006-01-25 10:55 UTC] sniper@php.net
See also bug #33760

 [2006-01-25 10:55 UTC] tony2001@php.net
Mike. this is related to your patch for #33760.
Please take a look.
 [2006-01-25 11:11 UTC] misiek at dione dot ids dot pl
This is how I see it. It's not problem in curl module. It's problem with callback handling in entire php. openssl allows only single callback function for entire application. curl and pgsql are just two things that happen to trigger the problem.

Now curl tries to initialize openssl and then to setup own callbacks. pgsql via libpq does the same thing. It again initializes already initialized openssl and setupts own callbacks again.

Every next module which uses openssl callbacks will be problematic unless initialization and callback handling will be done in upper layer (php itself) once for all modules. Maybe other solution (like initializing only once in first module) would also work...
 [2006-01-25 11:16 UTC] tony2001@php.net
>curl tries to initialize openssl and then to setup own callbacks.
>pgsql via libpq does the same thing.
"curl" here means ext/curl, while ext/pgsql doesn't set its handlers, libpq does that.
So personally I don't see a way to handle it, if an *external* library changes callbacks that were set in PHP extension.
I guess the library should be fixed first.
 [2006-01-25 11:21 UTC] misiek at dione dot ids dot pl
There are PQregisterThreadLock() and PQinitSSL() in libpq which allow to move initialization from libpq to application.
 [2006-01-25 11:21 UTC] mike@php.net
Well, the problem apparently is, that PHP links with lots of libraries using openssl and even openssl itself.

Some libs like libcurl leave it up to you to define crypto locking callbacks while obviously libraries like libpq define their own if we don't.

We'd need openssl crypto locking callbacks for all PHP once and adjust extensions, which link libraries that would define their own callbacks, accordingly.

This is just my best bet.


 [2006-01-25 11:46 UTC] mike@php.net
A temporary fix could be to reset

	CRYPTO_set_id_callback(php_curl_ssl_id);
	CRYPTO_set_locking_callback(php_curl_ssl_lock);

prior calling curl_global_cleanup().
 [2006-01-26 14:28 UTC] mike@php.net
This bug has been fixed in CVS.

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/.
 
Thank you for the report, and for helping us make PHP better.


 [2006-01-26 14:48 UTC] misiek at dione dot ids dot pl
That ,,fix'' doesn't sound like fix, it's rather hidding things under carpet.

libpq used by ext/pgsql sets own callbacks and curl resets them to it's own :/
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 18:02:13 2014 UTC