aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqcomm.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2015-05-18 10:02:31 -0400
committerNoah Misch <noah@leadboat.com>2015-05-18 10:02:31 -0400
commitb0ce385032d72d6acf1e330f733013553fe6affe (patch)
treeeeb158b7e34bc5cda085464767eee2274b0a5407 /src/backend/libpq/pqcomm.c
parent8cc7a4c5fdbe43b9b16b4cf3e07c8115107a8d4e (diff)
downloadpostgresql-b0ce385032d72d6acf1e330f733013553fe6affe.tar.gz
postgresql-b0ce385032d72d6acf1e330f733013553fe6affe.zip
Prevent a double free by not reentering be_tls_close().
Reentering this function with the right timing caused a double free, typically crashing the backend. By synchronizing a disconnection with the authentication timeout, an unauthenticated attacker could achieve this somewhat consistently. Call be_tls_close() solely from within proc_exit_prepare(). Back-patch to 9.0 (all supported versions). Benkocs Norbert Attila Security: CVE-2015-3165
Diffstat (limited to 'src/backend/libpq/pqcomm.c')
-rw-r--r--src/backend/libpq/pqcomm.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index fcdbfcea07b..6667cf94c64 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -220,32 +220,45 @@ socket_comm_reset(void)
/* --------------------------------
* socket_close - shutdown libpq at backend exit
*
- * Note: in a standalone backend MyProcPort will be null,
- * don't crash during exit...
+ * This is the one pg_on_exit_callback in place during BackendInitialize().
+ * That function's unusual signal handling constrains that this callback be
+ * safe to run at any instant.
* --------------------------------
*/
static void
socket_close(int code, Datum arg)
{
+ /* Nothing to do in a standalone backend, where MyProcPort is NULL. */
if (MyProcPort != NULL)
{
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
#ifdef ENABLE_GSS
OM_uint32 min_s;
- /* Shutdown GSSAPI layer */
+ /*
+ * Shutdown GSSAPI layer. This section does nothing when interrupting
+ * BackendInitialize(), because pg_GSS_recvauth() makes first use of
+ * "ctx" and "cred".
+ */
if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
gss_release_cred(&min_s, &MyProcPort->gss->cred);
#endif /* ENABLE_GSS */
- /* GSS and SSPI share the port->gss struct */
+ /*
+ * GSS and SSPI share the port->gss struct. Since nowhere else does a
+ * postmaster child free this, doing so is safe when interrupting
+ * BackendInitialize().
+ */
free(MyProcPort->gss);
#endif /* ENABLE_GSS || ENABLE_SSPI */
- /* Cleanly shut down SSL layer */
+ /*
+ * Cleanly shut down SSL layer. Nowhere else does a postmaster child
+ * call this, so this is safe when interrupting BackendInitialize().
+ */
secure_close(MyProcPort);
/*