######################################################################## Title: Short explanation of the "socket unreachable" term I use to identify some games vulnerabilities Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ######################################################################## With "socket unreachable" or "socket termination" I mean a type of bug that affects some connection-less based programs (like games for example). The effect of this problem is that an UDP server is no longer able to see and handle the packets that arrives to it for various reasons and often CPU at 100%. Usually the causes are 2: ------------------------------------------------------------------------ Bad handling of the "Message too long" socket error ==> big UDP ------------------------------------------------------------------------ if the program uses a small buffer to read UDP packets and if a bigger packet arrives, the socket generates an "Message too long" error that the connection-less applications in listening mode must ignore or they will follow the exit or error instructions usually set by the developer to handle errors. Example: if(recvfrom(sock, buff, 2000, 0, NULL, NULL) < 0) socket_error(); In this case we have a buffer of 2000 bytes that reads data from the socket, but if we receive a packet of 2001 bytes we reach the socket_error() function for example used to close the server or the socket. Is possible to fix the problem using a buffer of 65536 bytes that is the maximum amount of data that can be received in an UDP packet or is also possible to check the exact socket error received and ignoring it if is "Message too long". ------------------------------------------------------------------------ FIONREAD and asynchronous sockets ==> zero-length UDP ------------------------------------------------------------------------ FIONREAD is used by some programs to handle the data received by sockets in asynchronous mode. The instructions that use it are made to check the amount of data in the socket's queue, so the result is ever zero if there is no new data but if an empty UDP packet (so containing zero bytes of data) is received the result continue to be ever zero also if in reality there is new data in the queue... it's logical. The effect is that any other packet is ignored because the socket's queue can be freed only when the queued packet is read but is impossible for the program to know if there is new data (result = 0). Example: if(ioctlsocket(sock, FIONREAD, &packet_length) < 0) socket_error(); if(packet_length) { // or if(packet_length > 0) { // read socket data (recvfrom) } In this example packet_length is the value that contains the "result", so the current amount of data in the socket's queue. If we receive an empty UDP packet packet_length will continue to be zero and we will not be able to read the new packets. FIONREAD should be NEVER used in connection-less server! Is better to use the select() or the FIONBIO asynchronous mode. Anyway this bug can be fixed reading the empty UDP packet when we receive it. Naturally exist also other possible causes but they are rare or application-specifics, an example is the following: http://aluigi.org/adv/lithsock-adv.txt ########################################################################