Package: libpq5 Version: 9.1.9-1 Severity: normal Tags: patch upstream I've had crashes with glibc detecting double free/memory corruption through mod_wsgi, Django, psycopg2, libpq, libssl.
Turns out that libpq is not thread-safe; it uses a global SSL_context and does not protect its use of it appropriately, resulting in crashes in libssl. The point at which it had been affecting me was during the call to SSL_CTX_use_certificate_chain_file in initialize_SSL in fe-secure.c There are several further vulnerable uses of SSL_context later within that function; the patch I'm attaching protects all of them using a single call to pthread_mutex_lock -- I've not bothered to investigate whether the subsequent uses of SSL_context are such that they require the context not be modified by other threads in the interim, or whether it would be safe to protect each use separately. I don't think the gain from doing so would be significant anyway, as this section of code is only used once during each connection setup. While I am using postgres 9.1 from wheezy, I note that this issue is not fixed in current postgres 9.3 beta2 upstream. Cheers, Nick -- System Information: Debian Release: 7.1 APT prefers stable APT policy: (990, 'stable'), (500, 'stable-updates') Architecture: amd64 (x86_64) Kernel: Linux 2.6.32-5-xen-amd64 (SMP w/4 CPU cores) Locale: LANG=en_NZ.UTF-8, LC_CTYPE=en_NZ.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages libpq5 depends on: ii libc6 2.13-38 ii libcomerr2 1.42.5-1.1 ii libgssapi-krb5-2 1.10.1+dfsg-5+deb7u1 ii libkrb5-3 1.10.1+dfsg-5+deb7u1 ii libldap-2.4-2 2.4.31-1+nmu2 ii libssl1.0.0 1.0.1e-2 libpq5 recommends no packages. libpq5 suggests no packages. -- no debconf information ===> patch follows Description: libpq thread safety fix Protect libpq use of global SSL_context with mutex. Author: Nick Phillips <n...@debian.org> Forwarded: no Last-Update: 2013-08-01 --- postgresql-9.1-9.1.9.orig/src/interfaces/libpq/fe-secure.c +++ postgresql-9.1-9.1.9/src/interfaces/libpq/fe-secure.c @@ -1089,6 +1089,10 @@ initialize_SSL(PGconn *conn) * sslcert settings are used for different connections in the same * process. */ +#ifdef ENABLE_THREAD_SAFETY + if (pthread_mutex_lock(&ssl_config_mutex)) + return -1; +#endif if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1) { char *err = SSLerrmessage(); @@ -1097,6 +1101,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("could not read certificate file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } if (SSL_use_certificate_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1) @@ -1107,6 +1114,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("could not read certificate file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } /* need to load the associated private key, too */ @@ -1145,6 +1155,9 @@ initialize_SSL(PGconn *conn) engine_str, err); SSLerrfree(err); free(engine_str); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } @@ -1159,6 +1172,9 @@ initialize_SSL(PGconn *conn) ENGINE_free(conn->engine); conn->engine = NULL; free(engine_str); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } @@ -1176,6 +1192,9 @@ initialize_SSL(PGconn *conn) ENGINE_free(conn->engine); conn->engine = NULL; free(engine_str); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } if (SSL_use_PrivateKey(conn->ssl, pkey) != 1) @@ -1190,6 +1209,9 @@ initialize_SSL(PGconn *conn) ENGINE_free(conn->engine); conn->engine = NULL; free(engine_str); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } @@ -1242,6 +1264,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("could not load private key file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } } @@ -1256,6 +1281,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("certificate does not match private key file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } @@ -1284,6 +1312,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("could not read root certificate file \"%s\": %s\n"), fnbuf, err); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } @@ -1311,6 +1342,9 @@ initialize_SSL(PGconn *conn) libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"), fnbuf); SSLerrfree(err); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; #endif } @@ -1341,10 +1375,16 @@ initialize_SSL(PGconn *conn) printfPQExpBuffer(&conn->errorMessage, libpq_gettext("root certificate file \"%s\" does not exist\n" "Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf); +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return -1; } } +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif return 0; } -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org