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

Commit 7a0d48a

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 05da361 commit 7a0d48a

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

src/backend/libpq/be-secure.c

-5
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,6 @@ open_server_SSL(Port *port)
990990
(errcode(ERRCODE_PROTOCOL_VIOLATION),
991991
errmsg("could not initialize SSL connection: %s",
992992
SSLerrmessage())));
993-
close_SSL(port);
994993
return -1;
995994
}
996995
if (!my_SSL_set_fd(port->ssl, port->sock))
@@ -999,7 +998,6 @@ open_server_SSL(Port *port)
999998
(errcode(ERRCODE_PROTOCOL_VIOLATION),
1000999
errmsg("could not set SSL socket: %s",
10011000
SSLerrmessage())));
1002-
close_SSL(port);
10031001
return -1;
10041002
}
10051003

@@ -1047,7 +1045,6 @@ open_server_SSL(Port *port)
10471045
err)));
10481046
break;
10491047
}
1050-
close_SSL(port);
10511048
return -1;
10521049
}
10531050

@@ -1076,7 +1073,6 @@ open_server_SSL(Port *port)
10761073
{
10771074
/* shouldn't happen */
10781075
pfree(peer_cn);
1079-
close_SSL(port);
10801076
return -1;
10811077
}
10821078

@@ -1090,7 +1086,6 @@ open_server_SSL(Port *port)
10901086
(errcode(ERRCODE_PROTOCOL_VIOLATION),
10911087
errmsg("SSL certificate's common name contains embedded null")));
10921088
pfree(peer_cn);
1093-
close_SSL(port);
10941089
return -1;
10951090
}
10961091

src/backend/libpq/pqcomm.c

+18-5
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

+10-1
Original file line numberDiff line numberDiff line change
@@ -3961,7 +3961,16 @@ BackendInitialize(Port *port)
39613961
* We arrange for a simple exit(1) if we receive SIGTERM or SIGQUIT or
39623962
* timeout while trying to collect the startup packet. Otherwise the
39633963
* postmaster cannot shutdown the database FAST or IMMED cleanly if a
3964-
* buggy client fails to send the packet promptly.
3964+
* buggy client fails to send the packet promptly. XXX it follows that
3965+
* the remainder of this function must tolerate losing control at any
3966+
* instant. Likewise, any pg_on_exit_callback registered before or during
3967+
* this function must be prepared to execute at any instant between here
3968+
* and the end of this function. Furthermore, affected callbacks execute
3969+
* partially or not at all when a second exit-inducing signal arrives
3970+
* after proc_exit_prepare() decrements on_proc_exit_index. (Thanks to
3971+
* that mechanic, callbacks need not anticipate more than one call.) This
3972+
* is fragile; it ought to instead follow the norm of handling interrupts
3973+
* at selected, safe opportunities.
39653974
*/
39663975
pqsignal(SIGTERM, startup_die);
39673976
pqsignal(SIGQUIT, startup_die);

0 commit comments

Comments
 (0)