Skip to content

Commit b0ce385

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 8cc7a4c commit b0ce385

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

src/backend/libpq/be-secure-openssl.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,6 @@ be_tls_open_server(Port *port)
353353
(errcode(ERRCODE_PROTOCOL_VIOLATION),
354354
errmsg("could not initialize SSL connection: %s",
355355
SSLerrmessage())));
356-
be_tls_close(port);
357356
return -1;
358357
}
359358
if (!my_SSL_set_fd(port, port->sock))
@@ -362,7 +361,6 @@ be_tls_open_server(Port *port)
362361
(errcode(ERRCODE_PROTOCOL_VIOLATION),
363362
errmsg("could not set SSL socket: %s",
364363
SSLerrmessage())));
365-
be_tls_close(port);
366364
return -1;
367365
}
368366
port->ssl_in_use = true;
@@ -419,7 +417,6 @@ be_tls_open_server(Port *port)
419417
err)));
420418
break;
421419
}
422-
be_tls_close(port);
423420
return -1;
424421
}
425422

@@ -449,7 +446,6 @@ be_tls_open_server(Port *port)
449446
{
450447
/* shouldn't happen */
451448
pfree(peer_cn);
452-
be_tls_close(port);
453449
return -1;
454450
}
455451

@@ -463,7 +459,6 @@ be_tls_open_server(Port *port)
463459
(errcode(ERRCODE_PROTOCOL_VIOLATION),
464460
errmsg("SSL certificate's common name contains embedded null")));
465461
pfree(peer_cn);
466-
be_tls_close(port);
467462
return -1;
468463
}
469464

src/backend/libpq/pqcomm.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,32 +220,45 @@ socket_comm_reset(void)
220220
/* --------------------------------
221221
* socket_close - shutdown libpq at backend exit
222222
*
223-
* Note: in a standalone backend MyProcPort will be null,
224-
* don't crash during exit...
223+
* This is the one pg_on_exit_callback in place during BackendInitialize().
224+
* That function's unusual signal handling constrains that this callback be
225+
* safe to run at any instant.
225226
* --------------------------------
226227
*/
227228
static void
228229
socket_close(int code, Datum arg)
229230
{
231+
/* Nothing to do in a standalone backend, where MyProcPort is NULL. */
230232
if (MyProcPort != NULL)
231233
{
232234
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
233235
#ifdef ENABLE_GSS
234236
OM_uint32 min_s;
235237

236-
/* Shutdown GSSAPI layer */
238+
/*
239+
* Shutdown GSSAPI layer. This section does nothing when interrupting
240+
* BackendInitialize(), because pg_GSS_recvauth() makes first use of
241+
* "ctx" and "cred".
242+
*/
237243
if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
238244
gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
239245

240246
if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
241247
gss_release_cred(&min_s, &MyProcPort->gss->cred);
242248
#endif /* ENABLE_GSS */
243-
/* GSS and SSPI share the port->gss struct */
244249

250+
/*
251+
* GSS and SSPI share the port->gss struct. Since nowhere else does a
252+
* postmaster child free this, doing so is safe when interrupting
253+
* BackendInitialize().
254+
*/
245255
free(MyProcPort->gss);
246256
#endif /* ENABLE_GSS || ENABLE_SSPI */
247257

248-
/* Cleanly shut down SSL layer */
258+
/*
259+
* Cleanly shut down SSL layer. Nowhere else does a postmaster child
260+
* call this, so this is safe when interrupting BackendInitialize().
261+
*/
249262
secure_close(MyProcPort);
250263

251264
/*

src/backend/postmaster/postmaster.c

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy