summaryrefslogtreecommitdiff
path: root/src/backend/tcop/backend_startup.c
diff options
context:
space:
mode:
authorHeikki Linnakangas2025-04-02 13:41:48 +0000
committerHeikki Linnakangas2025-04-02 13:41:48 +0000
commita460251f0a1ac987f0225203ff9593704da0b1a9 (patch)
tree009893fb5dc0e934b15abf6eabfe20fda63b3d4d /src/backend/tcop/backend_startup.c
parent285613c60a7aff5daaf281c67002483b0d26e715 (diff)
Make cancel request keys longer
Currently, the cancel request key is a 32-bit token, which isn't very much entropy. If you want to cancel another session's query, you can brute-force it. In most environments, an unauthorized cancellation of a query isn't very serious, but it nevertheless would be nice to have more protection from it. Hence make the key longer, to make it harder to guess. The longer cancellation keys are generated when using the new protocol version 3.2. For connections using version 3.0, short 4-bytes keys are still used. The new longer key length is not hardcoded in the protocol anymore, the client is expected to deal with variable length keys, up to 256 bytes. This flexibility allows e.g. a connection pooler to add more information to the cancel key, which might be useful for finding the connection. Reviewed-by: Jelte Fennema-Nio <[email protected]> Reviewed-by: Robert Haas <[email protected]> (earlier versions) Discussion: https://www.postgresql.org/message-id/[email protected]
Diffstat (limited to 'src/backend/tcop/backend_startup.c')
-rw-r--r--src/backend/tcop/backend_startup.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/src/backend/tcop/backend_startup.c b/src/backend/tcop/backend_startup.c
index 84e1c6f2831..dde8d5b3517 100644
--- a/src/backend/tcop/backend_startup.c
+++ b/src/backend/tcop/backend_startup.c
@@ -60,6 +60,7 @@ ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY};
static void BackendInitialize(ClientSocket *client_sock, CAC_state cac);
static int ProcessSSLStartup(Port *port);
static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done);
+static void ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen);
static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options);
static void process_startup_packet_die(SIGNAL_ARGS);
static void StartupPacketTimeoutHandler(void);
@@ -565,28 +566,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
if (proto == CANCEL_REQUEST_CODE)
{
- /*
- * The client has sent a cancel request packet, not a normal
- * start-a-new-connection packet. Perform the necessary processing.
- * Nothing is sent back to the client.
- */
- CancelRequestPacket *canc;
- int backendPID;
- int32 cancelAuthCode;
-
- if (len != sizeof(CancelRequestPacket))
- {
- ereport(COMMERROR,
- (errcode(ERRCODE_PROTOCOL_VIOLATION),
- errmsg("invalid length of startup packet")));
- return STATUS_ERROR;
- }
- canc = (CancelRequestPacket *) buf;
- backendPID = (int) pg_ntoh32(canc->backendPID);
- cancelAuthCode = (int32) pg_ntoh32(canc->cancelAuthCode);
-
- if (backendPID != 0)
- SendCancelRequest(backendPID, cancelAuthCode);
+ ProcessCancelRequestPacket(port, buf, len);
/* Not really an error, but we don't want to proceed further */
return STATUS_ERROR;
}
@@ -887,6 +867,37 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
}
/*
+ * The client has sent a cancel request packet, not a normal
+ * start-a-new-connection packet. Perform the necessary processing. Nothing
+ * is sent back to the client.
+ */
+static void
+ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen)
+{
+ CancelRequestPacket *canc;
+ int len;
+
+ if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode))
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("invalid length of query cancel packet")));
+ return;
+ }
+ len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode);
+ if (len == 0 || len > 256)
+ {
+ ereport(COMMERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("invalid length of query cancel key")));
+ return;
+ }
+
+ canc = (CancelRequestPacket *) pkt;
+ SendCancelRequest(pg_ntoh32(canc->backendPID), canc->cancelAuthCode, len);
+}
+
+/*
* Send a NegotiateProtocolVersion to the client. This lets the client know
* that they have either requested a newer minor protocol version than we are
* able to speak, or at least one protocol option that we don't understand, or