Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f4c12b4

Browse files
committed
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
1 parent b9403de commit f4c12b4

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

src/backend/libpq/be-secure.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,6 @@ open_server_SSL(Port *port)
887887
(errcode(ERRCODE_PROTOCOL_VIOLATION),
888888
errmsg("could not initialize SSL connection: %s",
889889
SSLerrmessage())));
890-
close_SSL(port);
891890
return -1;
892891
}
893892
if (!my_SSL_set_fd(port->ssl, port->sock))
@@ -896,7 +895,6 @@ open_server_SSL(Port *port)
896895
(errcode(ERRCODE_PROTOCOL_VIOLATION),
897896
errmsg("could not set SSL socket: %s",
898897
SSLerrmessage())));
899-
close_SSL(port);
900898
return -1;
901899
}
902900

@@ -944,7 +942,6 @@ open_server_SSL(Port *port)
944942
err)));
945943
break;
946944
}
947-
close_SSL(port);
948945
return -1;
949946
}
950947

@@ -973,7 +970,6 @@ open_server_SSL(Port *port)
973970
{
974971
/* shouldn't happen */
975972
pfree(peer_cn);
976-
close_SSL(port);
977973
return -1;
978974
}
979975

@@ -987,7 +983,6 @@ open_server_SSL(Port *port)
987983
(errcode(ERRCODE_PROTOCOL_VIOLATION),
988984
errmsg("SSL certificate's common name contains embedded null")));
989985
pfree(peer_cn);
990-
close_SSL(port);
991986
return -1;
992987
}
993988

src/backend/libpq/pqcomm.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,32 +182,45 @@ pq_comm_reset(void)
182182
/* --------------------------------
183183
* pq_close - shutdown libpq at backend exit
184184
*
185-
* Note: in a standalone backend MyProcPort will be null,
186-
* don't crash during exit...
185+
* This is the one pg_on_exit_callback in place during BackendInitialize().
186+
* That function's unusual signal handling constrains that this callback be
187+
* safe to run at any instant.
187188
* --------------------------------
188189
*/
189190
static void
190191
pq_close(int code, Datum arg)
191192
{
193+
/* Nothing to do in a standalone backend, where MyProcPort is NULL. */
192194
if (MyProcPort != NULL)
193195
{
194196
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
195197
#ifdef ENABLE_GSS
196198
OM_uint32 min_s;
197199

198-
/* Shutdown GSSAPI layer */
200+
/*
201+
* Shutdown GSSAPI layer. This section does nothing when interrupting
202+
* BackendInitialize(), because pg_GSS_recvauth() makes first use of
203+
* "ctx" and "cred".
204+
*/
199205
if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
200206
gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
201207

202208
if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
203209
gss_release_cred(&min_s, &MyProcPort->gss->cred);
204210
#endif /* ENABLE_GSS */
205-
/* GSS and SSPI share the port->gss struct */
206211

212+
/*
213+
* GSS and SSPI share the port->gss struct. Since nowhere else does a
214+
* postmaster child free this, doing so is safe when interrupting
215+
* BackendInitialize().
216+
*/
207217
free(MyProcPort->gss);
208218
#endif /* ENABLE_GSS || ENABLE_SSPI */
209219

210-
/* Cleanly shut down SSL layer */
220+
/*
221+
* Cleanly shut down SSL layer. Nowhere else does a postmaster child
222+
* call this, so this is safe when interrupting BackendInitialize().
223+
*/
211224
secure_close(MyProcPort);
212225

213226
/*

src/backend/postmaster/postmaster.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3855,7 +3855,16 @@ BackendInitialize(Port *port)
38553855
* We arrange for a simple exit(1) if we receive SIGTERM or SIGQUIT or
38563856
* timeout while trying to collect the startup packet. Otherwise the
38573857
* postmaster cannot shutdown the database FAST or IMMED cleanly if a
3858-
* buggy client fails to send the packet promptly.
3858+
* buggy client fails to send the packet promptly. XXX it follows that
3859+
* the remainder of this function must tolerate losing control at any
3860+
* instant. Likewise, any pg_on_exit_callback registered before or during
3861+
* this function must be prepared to execute at any instant between here
3862+
* and the end of this function. Furthermore, affected callbacks execute
3863+
* partially or not at all when a second exit-inducing signal arrives
3864+
* after proc_exit_prepare() decrements on_proc_exit_index. (Thanks to
3865+
* that mechanic, callbacks need not anticipate more than one call.) This
3866+
* is fragile; it ought to instead follow the norm of handling interrupts
3867+
* at selected, safe opportunities.
38593868
*/
38603869
pqsignal(SIGTERM, startup_die);
38613870
pqsignal(SIGQUIT, startup_die);

0 commit comments

Comments
 (0)