From 1a081d10e6c71a5b5b2db76081227677f06b47b3 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Mon, 1 Jun 2020 09:53:23 +0200 Subject: [PATCH] fix heap buffer overflows in UDP code (CVE-2019-20797) (#85) Origin: https://github.com/coelckers/prboom-plus * fix heap buffer overflows in UDP code (CVE-2019-20797) * Limit length of buffer passed over to ChecksumPacket(). Patch taken from the OP at https://logicaltrust.net/blog/2019/10/prboom1.html * Never send more than one second worth of tics (i.e. 35) in both the main() routine in d_server.c and NetUpdate() in d_client.c. This avoids overflows of the allocated UDF buffer with a fixed size of 10000 bytes. Theoretically, up to about 35 seconds could be sent in the client code and up to about 7 seconds in the server code, but the network game would be unplayable with such a lag anyway. Client code: pkt_size = 8 + 2 + X * 8 (= 9810 for X = 35*35) Server code: pkt_size = 8 + 1 + X * (1 + 4 * (1 + 8)) (= 9074 for X = 7 * 35) Fixes: #84 * limit number of sent tics to 128 * fix brain bug --- src/SDL/i_network.c | 2 +- src/d_client.c | 2 +- src/d_server.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SDL/i_network.c b/src/SDL/i_network.c index 89edab78..7e02706a 100644 --- a/src/SDL/i_network.c +++ b/src/SDL/i_network.c @@ -240,7 +240,7 @@ size_t I_GetPacket(packet_header_t* buffer, size_t buflen) checksum=buffer->checksum; buffer->checksum=0; if ( (status!=0) && (len>0)) { - byte psum = ChecksumPacket(buffer, udp_packet->len); + byte psum = ChecksumPacket(buffer, len); // https://logicaltrust.net/blog/2019/10/prboom1.html /* fprintf(stderr, "recvlen = %u, stolen = %u, csum = %u, psum = %u\n", udp_packet->len, len, checksum, psum); */ if (psum == checksum) return len; diff --git a/src/d_client.c b/src/d_client.c index 7ce74d4e..054bc595 100644 --- a/src/d_client.c +++ b/src/d_client.c @@ -351,7 +351,7 @@ void NetUpdate(void) int sendtics; remotesend -= xtratics; if (remotesend < 0) remotesend = 0; - sendtics = maketic - remotesend; + sendtics = MIN(maketic - remotesend, 128); // limit number of sent tics (CVE-2019-20797) { size_t pkt_size = sizeof(packet_header_t) + 2 + sendtics * sizeof(ticcmd_t); packet_header_t *packet = Z_Malloc(pkt_size, PU_STATIC, NULL); diff --git a/src/d_server.c b/src/d_server.c index 1269a861..39c2e3cd 100644 --- a/src/d_server.c +++ b/src/d_server.c @@ -682,7 +682,7 @@ int main(int argc, char** argv) int tics; if (lowtic <= remoteticto[i]) continue; if ((remoteticto[i] -= xtratics) < 0) remoteticto[i] = 0; - tics = lowtic - remoteticto[i]; + tics = MIN(lowtic - remoteticto[i], 128); // limit number of sent tics (CVE-2019-20797) { byte *p; packet = malloc(sizeof(packet_header_t) + 1 + -- 2.26.2