libpq does not manage SSL callbacks properly when other libraries are involved.

From: Russell Smith <mr-russ(at)pws(dot)com(dot)au>
To: pgsql-bugs(at)postgresql(dot)org
Subject: libpq does not manage SSL callbacks properly when other libraries are involved.
Date: 2008-06-25 09:00:21
Message-ID: 48620925.6070806@pws.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs pgsql-hackers

Hi,

After experiencing a seg fault on RHEL5's command line php, I did the
following investigation.

As I dot not have a RHEL5 box available with debugging tools, I
reproduced the bug on CentOS5.

Reproduction on Centos5
-----------------------
[root(at)unknown-00-16-3e-30-f0-0d ~]# php -f test-pgsql.php
PHP Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[08006] [7] FATAL: no pg_hba.conf entry for host
"59.167.146.4", user "nouser", database "fsd", SSL off' in
/root/test-pgsql.php:3
Stack trace:
#0 /root/test-pgsql.php(3): PDO->__construct('pgsql:host=thoe...',
'nouser', 'nopass')
#1 {main}
thrown in /root/test-pgsql.php on line 3
Segmentation fault

[root(at)unknown-00-16-3e-30-f0-0d ~]# cat test-pgsql.php
<?php

$x = new
PDO("pgsql:host=connectableserver;port=5437;dbname=fsd","nouser","nopass");

?>
[root(at)unknown-00-16-3e-30-f0-0d ~]# php -f test-pgsql.php
PHP Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[08006] [7] FATAL: no pg_hba.conf entry for host
"59.167.146.4", user "nouser", database "fsd", SSL off' in
/root/test-pgsql.php:3
Stack trace:
#0 /root/test-pgsql.php(3): PDO->__construct('pgsql:host=thoe...',
'nouser', 'nopass')
#1 {main}
thrown in /root/test-pgsql.php on line 3
Segmentation fault
[root(at)unknown-00-16-3e-30-f0-0d ~]# gdb php
GNU gdb Red Hat Linux (6.5-25.el5_1.1rh)
Copyright (C) 2006 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 "i386-redhat-linux-gnu"...(no debugging
symbols found)
Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run -f test-pgsql.php
Starting program: /usr/bin/php -f test-pgsql.php
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
[Thread debugging using libthread_db enabled]
[New Thread -1208912160 (LWP 27037)]
PHP Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[08006] [7] FATAL: no pg_hba.conf entry for host
"59.167.146.4", user "nouser", database "fsd", SSL off' in
/root/test-pgsql.php:3
Stack trace:
#0 /root/test-pgsql.php(3): PDO->__construct('pgsql:host=thoe...',
'nouser', 'nopass')
#1 {main}
thrown in /root/test-pgsql.php on line 3

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1208912160 (LWP 27037)]
0x003248b0 in ?? ()
(gdb) bt
#0 0x003248b0 in ?? ()
#1 0x003996c5 in CRYPTO_lock () from /lib/libcrypto.so.6
#2 0x003efdbd in ERR_get_implementation () from /lib/libcrypto.so.6
#3 0x003efb90 in ERR_free_strings () from /lib/libcrypto.so.6
#4 0x00588107 in Curl_ossl_cleanup () from /usr/lib/libcurl.so.3
#5 0x00599370 in Curl_ssl_cleanup () from /usr/lib/libcurl.so.3
#6 0x005910c3 in curl_global_cleanup () from /usr/lib/libcurl.so.3
#7 0x0808d85b in zm_shutdown_curl ()
#8 0x081cecbe in module_destructor ()
#9 0x081d42a7 in zend_hash_quick_find ()
#10 0x081d4538 in zend_hash_graceful_reverse_destroy ()
#11 0x081cb89e in zend_shutdown ()
#12 0x0818e0ff in php_module_shutdown ()
#13 0x0824168b in main ()

After googling around a bit, I found these relevant bug links;

http://bugs.php.net/bug.php?id=40926
https://bugs.launchpad.net/ubuntu/+source/php5/+bug/63141
http://bugs.debian.org/411982 <http://bugs.debian.org/411982>

Following up the php bug report appeared to give the most useful outcome;

This is part of a comment from the php bug comment history;

*[12 Nov 2007 2:45pm UTC] sam at zoy dot org*

Hello, I did read the sources and studied them, and I can confirm
that it is a matter of callback jumping to an invalid address.

libpq's init_ssl_system() installs callbacks by calling
CRYPTO_set_id_callback() and CRYPTO_set_locking_callback(). This
function is called each time initialize_SSL() is called (for instance
through the PHP pg_connect() function) and does not keep a reference
counter, so libpq's destroy_SSL() has no way to know that it should
call a destroy_ssl_system() function, and there is no such function
anyway. So the callbacks are never removed.

But then, upon cleanup, PHP calls zend_shutdown() which properly
unloads pgsql.so and therefore the unused libpq.

Finally, the zend_shutdown procedure calls zm_shutdown_curl()
which in turn calls curl_global_cleanup() which leads to an
ERR_free_strings() call and eventually a CRYPTO_lock() call.
CRYPTO_lock() checks whether there are any callbacks to call,
finds one (the one installed by libpg), calls it, and crashes
because libpq was unloaded and hence the callback is no longer
in mapped memory.

After noting that it is SSL related, I adjusted my test script to show
the following (added sslmode=disable);

[root(at)unknown-00-16-3e-30-f0-0d ~]# cat test-pgsql.php

<?php

$x = new PDO("pgsql:host=connectablehost;port=5437;dbname=fsd;sslmode=disable","nouser","nopass");

?>

[root(at)unknown-00-16-3e-30-f0-0d ~]# php -f test-pgsql.php

PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[08006] [7] FATAL: no pg_hba.conf entry for host "xx.xx.xx.xx", user "nouser", database "fsd", SSL off' in /root/test-pgsql.php:3

Stack trace:

#0 /root/test-pgsql.php(3): PDO->__construct('pgsql:host=thoe...', 'nouser', 'nopass')

#1 {main}

thrown in /root/test-pgsql.php on line 3

As a result, the crash has gone away. Are the comments in the PHP
comment accurate and is it reasonable to count calls to SSL in the way
suggested? As currently the callback remains even if libpq is unloaded
from memory, which is what's causing this problem. The callback should
be unregistered when we close our own SSL stuff?

Is it possible to get this fixed and possibly backported?

Thanks

Russell Smith

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Bill Moran 2008-06-25 12:06:22 Re: Reg : Data base deletion
Previous Message Ati Rosselet 2008-06-25 08:26:41 just a question re: submitted bug...

Browse pgsql-hackers by date

  From Date Subject
Next Message Heikki Linnakangas 2008-06-25 09:58:04 Re: the un-vacuumable table
Previous Message Heikki Linnakangas 2008-06-25 08:51:29 Re: proposal for smaller indexes on index-ordered tables