mirror of
https://github.com/postgres/postgres.git
synced 2025-05-18 17:41:14 +03:00
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
This commit is contained in:
parent
b9403dedc5
commit
f4c12b415f
@ -887,7 +887,6 @@ open_server_SSL(Port *port)
|
|||||||
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||||
errmsg("could not initialize SSL connection: %s",
|
errmsg("could not initialize SSL connection: %s",
|
||||||
SSLerrmessage())));
|
SSLerrmessage())));
|
||||||
close_SSL(port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!my_SSL_set_fd(port->ssl, port->sock))
|
if (!my_SSL_set_fd(port->ssl, port->sock))
|
||||||
@ -896,7 +895,6 @@ open_server_SSL(Port *port)
|
|||||||
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||||
errmsg("could not set SSL socket: %s",
|
errmsg("could not set SSL socket: %s",
|
||||||
SSLerrmessage())));
|
SSLerrmessage())));
|
||||||
close_SSL(port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -944,7 +942,6 @@ aloop:
|
|||||||
err)));
|
err)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close_SSL(port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,7 +970,6 @@ aloop:
|
|||||||
{
|
{
|
||||||
/* shouldn't happen */
|
/* shouldn't happen */
|
||||||
pfree(peer_cn);
|
pfree(peer_cn);
|
||||||
close_SSL(port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,7 +983,6 @@ aloop:
|
|||||||
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||||
errmsg("SSL certificate's common name contains embedded null")));
|
errmsg("SSL certificate's common name contains embedded null")));
|
||||||
pfree(peer_cn);
|
pfree(peer_cn);
|
||||||
close_SSL(port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,32 +182,45 @@ pq_comm_reset(void)
|
|||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
* pq_close - shutdown libpq at backend exit
|
* pq_close - shutdown libpq at backend exit
|
||||||
*
|
*
|
||||||
* Note: in a standalone backend MyProcPort will be null,
|
* This is the one pg_on_exit_callback in place during BackendInitialize().
|
||||||
* don't crash during exit...
|
* That function's unusual signal handling constrains that this callback be
|
||||||
|
* safe to run at any instant.
|
||||||
* --------------------------------
|
* --------------------------------
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
pq_close(int code, Datum arg)
|
pq_close(int code, Datum arg)
|
||||||
{
|
{
|
||||||
|
/* Nothing to do in a standalone backend, where MyProcPort is NULL. */
|
||||||
if (MyProcPort != NULL)
|
if (MyProcPort != NULL)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
|
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
|
||||||
#ifdef ENABLE_GSS
|
#ifdef ENABLE_GSS
|
||||||
OM_uint32 min_s;
|
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)
|
if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
|
||||||
gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
|
gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
|
||||||
|
|
||||||
if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
|
if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
|
||||||
gss_release_cred(&min_s, &MyProcPort->gss->cred);
|
gss_release_cred(&min_s, &MyProcPort->gss->cred);
|
||||||
#endif /* ENABLE_GSS */
|
#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);
|
free(MyProcPort->gss);
|
||||||
#endif /* ENABLE_GSS || ENABLE_SSPI */
|
#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);
|
secure_close(MyProcPort);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3855,7 +3855,16 @@ BackendInitialize(Port *port)
|
|||||||
* We arrange for a simple exit(1) if we receive SIGTERM or SIGQUIT or
|
* We arrange for a simple exit(1) if we receive SIGTERM or SIGQUIT or
|
||||||
* timeout while trying to collect the startup packet. Otherwise the
|
* timeout while trying to collect the startup packet. Otherwise the
|
||||||
* postmaster cannot shutdown the database FAST or IMMED cleanly if a
|
* postmaster cannot shutdown the database FAST or IMMED cleanly if a
|
||||||
* buggy client fails to send the packet promptly.
|
* buggy client fails to send the packet promptly. XXX it follows that
|
||||||
|
* the remainder of this function must tolerate losing control at any
|
||||||
|
* instant. Likewise, any pg_on_exit_callback registered before or during
|
||||||
|
* this function must be prepared to execute at any instant between here
|
||||||
|
* and the end of this function. Furthermore, affected callbacks execute
|
||||||
|
* partially or not at all when a second exit-inducing signal arrives
|
||||||
|
* after proc_exit_prepare() decrements on_proc_exit_index. (Thanks to
|
||||||
|
* that mechanic, callbacks need not anticipate more than one call.) This
|
||||||
|
* is fragile; it ought to instead follow the norm of handling interrupts
|
||||||
|
* at selected, safe opportunities.
|
||||||
*/
|
*/
|
||||||
pqsignal(SIGTERM, startup_die);
|
pqsignal(SIGTERM, startup_die);
|
||||||
pqsignal(SIGQUIT, startup_die);
|
pqsignal(SIGQUIT, startup_die);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user