Subject: fix for vulnerability CVE-2010-4168 for OpenTTD 1.0.0 - 1.0.4 (Denial of service (server/client) via invalid read) From: OpenTTD developer team Origin: backport, http://vcs.openttd.org/svn/changeset/21182 When a client disconnects, without sending the "quit" or "client error" message, the server has a chance of reading and writing a just freed piece of memory. The chance depends on when the disconnect is noticed, whether OpenTTD can write to the socket, and whether there are packets from the client waiting to be processed. The writing can only happen while the server is sending the map. For clients there is a chance that, upon reconnect after being disconnected during the join process, a just freed piece of memory is read. Depending on what happens directly after freeing the memory there is a chance that a segmentation fault, and thus a denial of service will occur. The attached patch does not change network compatability at all. Index: src/network/network_server.cpp =================================================================== --- src/network/network_server.cpp (revision 21182) +++ src/network/network_server.cpp (working copy) @@ -412,8 +412,7 @@ } /* Send all packets (forced) and check if we have send it all */ - cs->Send_Packets(); - if (cs->IsPacketQueueEmpty()) { + if (cs->Send_Packets() && cs->IsPacketQueueEmpty()) { /* All are sent, increase the sent_packets */ sent_packets *= 2; } else { Index: src/network/network.cpp =================================================================== --- src/network/network.cpp (revision 21182) +++ src/network/network.cpp (working copy) @@ -675,7 +675,7 @@ FOR_ALL_CLIENT_SOCKETS(cs) { if (!_network_server) { SEND_COMMAND(PACKET_CLIENT_QUIT)(); - cs->Send_Packets(); + cs->Send_Packets(true); } NetworkCloseClient(cs, NETWORK_RECV_STATUS_CONN_LOST); } @@ -1006,9 +1006,7 @@ NetworkClientSocket *cs; FOR_ALL_CLIENT_SOCKETS(cs) { if (cs->writable) { - cs->Send_Packets(); - - if (cs->status == STATUS_MAP) { + if (cs->Send_Packets() && cs->status == STATUS_MAP) { /* This client is in the middle of a map-send, call the function for that */ SEND_COMMAND(PACKET_SERVER_MAP)(cs); }