summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier2012-10-23 08:01:15 +0000
committerMichael Paquier2012-10-23 08:01:15 +0000
commit786d74ba8bf8058a504df6ac6b20023cfe260991 (patch)
tree4163bb5a277923d9324acea2c596de47ea0ef53d
parent23220741845f72669e5bd4bb5825d8818fb16223 (diff)
Fix memory corruption for GTM/backend buffer on backend side
This commit fixes an issue that corrupted data from GTM on Postgres backend for snapshots and transaction IDs. The origin of the failure was the startup package of GTM that was not initialized correctly, so the data it contained could be used as snapshot or GXID data in very particular situations like when a vacuum freeze is kicked on a system table due to the table oldest XID being too old in accordance to settings like autovacuum_freeze_max_age and autovacuum_freeze_min_age. In order to reproduce easily the problem, I personnally had to use a cluster of 5 nodes with autovacuum_freeze_max_age at its minimum value, then wait for a system table to be automatically vacuumed. Once the vacuum was kicked, the buffer of 16kb used at backend side to store messages from GTM got corrupted, having as consequence to generate multiple types of crashes related to memory allocation (realloc and malloc calls). It is really surprising that this issue was not reproducible in other circumstances and could only be spotted with a forced vacuum as it was a pretty general problem related to GTM communication, and valgrind helped to spot pretty easily the memory area that was corrupted.
-rw-r--r--src/gtm/client/fe-connect.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/gtm/client/fe-connect.c b/src/gtm/client/fe-connect.c
index a3add0e1f4..bfcb5f4e54 100644
--- a/src/gtm/client/fe-connect.c
+++ b/src/gtm/client/fe-connect.c
@@ -665,7 +665,11 @@ keep_going: /* We will come back to here until there is
case CONNECTION_MADE:
{
- GTM_StartupPacket sp;
+ GTM_StartupPacket *sp = (GTM_StartupPacket *)
+ malloc(sizeof(GTM_StartupPacket));
+ int packetlen = sizeof(GTM_StartupPacket);
+
+ MemSet(sp, 0, sizeof(GTM_StartupPacket));
/*
* Build a startup packet. We tell the GTM server/proxy our
@@ -675,9 +679,9 @@ keep_going: /* We will come back to here until there is
* server know about it so that some special headers are
* handled correctly by the server.
*/
- strcpy(sp.sp_node_name, conn->gc_node_name);
- sp.sp_remotetype = conn->remote_type;
- sp.sp_ispostmaster = conn->is_postmaster;
+ strncpy(sp->sp_node_name, conn->gc_node_name, SP_NODE_NAME);
+ sp->sp_remotetype = conn->remote_type;
+ sp->sp_ispostmaster = conn->is_postmaster;
/*
* Send the startup packet.
@@ -685,7 +689,7 @@ keep_going: /* We will come back to here until there is
* Theoretically, this could block, but it really shouldn't
* since we only got here if the socket is write-ready.
*/
- if (pqPacketSend(conn, 'A', &sp, sizeof (GTM_StartupPacket)) != STATUS_OK)
+ if (pqPacketSend(conn, 'A', (char *)sp, packetlen) != STATUS_OK)
{
appendGTMPQExpBuffer(&conn->errorMessage,
"could not send startup packet: \n");
@@ -693,6 +697,10 @@ keep_going: /* We will come back to here until there is
}
conn->status = CONNECTION_AWAITING_RESPONSE;
+
+ /* Clean up startup packet */
+ free(sp);
+
return PGRES_POLLING_READING;
}