# colinux-bridged-net-daemon.exe (and other net daemons) crashes under # heavy load (colinux version 0.6.4). # # This patch fixed the Bugs item #1517979 and #1551076 # http://sourceforge.net/tracker/?func=detail&atid=622063&aid=1517979&group_id=98788 # http://sourceforge.net/tracker/?func=detail&atid=622063&aid=1551076&group_id=98788 # # 2006-09-11 Mitch Bradley: Initail version of this patch. # 2006-09-11 Henry: Fix a sign and struct base. Compiled ready, short tested. # Loglevel 10. Source face lifts. # 2006-09-12 Mitch: Testresult OK. # 2006-09-12 Henry: Add similar code for all other daemons # (tap/conet, slirp, serial device). # # Thanks goes to Mitch Bradley # old_revision [298ba6d65becdd36d753141d06a4dd623b83284d] # # patch "src/colinux/os/winnt/user/conet-bridged-daemon/main.c" # from [44c66305e18c7947028906f5f70a947e9aa1e782] # to [19ca75df910e825ee6f2743972522268da4dd2ba] # # patch "src/colinux/os/winnt/user/conet-daemon/main.c" # from [f532682d40fc2b2d2731d943724829078cfbf5bd] # to [9065bf775181547ff893841368ad9423788aeb3f] # # patch "src/colinux/os/winnt/user/conet-slirp-daemon/main.c" # from [e201c6236a8c99d4fa3624c0b4d6978e850249d3] # to [8fafa7e9bd35bc02b6fc5b6034cbe797bfbf7731] # # patch "src/colinux/os/winnt/user/coserial-daemon/main.c" # from [a534e263449c4fb1d9cc22c0429b902143b47503] # to [c5e821921987cb0ea329bf687c17424dfc49faa5] # ============================================================ --- src/colinux/os/winnt/user/conet-bridged-daemon/main.c 44c66305e18c7947028906f5f70a947e9aa1e782 +++ src/colinux/os/winnt/user/conet-bridged-daemon/main.c 19ca75df910e825ee6f2743972522268da4dd2ba @@ -41,6 +41,7 @@ OVERLAPPED write_overlapped; char buffer[0x10000]; unsigned long size; + unsigned long offset; } co_win32_overlapped_t; typedef struct co_win32_pcap { @@ -114,29 +115,34 @@ /* Received packet from daemon. */ co_message_t *message; char * buffer = overlapped->buffer; - long size_left = overlapped->size; - unsigned long message_size; + long size_left = overlapped->size + overlapped->offset; - do { + while (size_left > 0) { message = (co_message_t *)buffer; - message_size = message->size + sizeof (co_message_t); - buffer += message_size; - size_left -= message_size; - /* Check buffer overrun */ - if (size_left < 0) { - co_debug("Error: Message incomplete (%ld)\n", size_left); - return CO_RC(ERROR); + // Do not dereference message->size unless we have a complete header + if ( (size_left < sizeof (co_message_t)) || + (size_left < (message->size + sizeof (co_message_t))) ) { + // Copy partial message down to bottom of buffer and + // adjust offset so the next read splices the new data + // after the old data + memcpy(overlapped->buffer, buffer, size_left); + overlapped->offset = size_left; + co_debug_lvl(network, 10, "Preserving 0x%x trailing bytes\n", size_left); + return CO_RC(OK); } co_debug_lvl(network, 12, "sending to pcap (0x%x size 0x%x)\n", message->data, message->size); /* Send packet using pcap. */ pcap_rc = pcap_sendpacket(pcap_packet.adhandle, - message->data, message->size); + message->data, message->size); co_debug_lvl(network, 13, "sent (%x)\n", pcap_rc); - } while (size_left > 0); + buffer += message->size + sizeof (co_message_t); + size_left -= message->size + sizeof (co_message_t); + } + overlapped->offset = 0; return CO_RC(OK); } @@ -179,8 +185,8 @@ while (TRUE) { result = ReadFile(overlapped->handle, - &overlapped->buffer, - sizeof (overlapped->buffer), + overlapped->buffer + overlapped->offset, + sizeof (overlapped->buffer) - overlapped->offset, &overlapped->size, &overlapped->read_overlapped); @@ -238,6 +244,7 @@ overlapped->handle = handle; overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); + overlapped->offset = 0; overlapped->read_overlapped.Offset = 0; overlapped->read_overlapped.OffsetHigh = 0; ============================================================ --- src/colinux/os/winnt/user/conet-daemon/main.c f532682d40fc2b2d2731d943724829078cfbf5bd +++ src/colinux/os/winnt/user/conet-daemon/main.c 9065bf775181547ff893841368ad9423788aeb3f @@ -33,6 +33,7 @@ OVERLAPPED write_overlapped; char buffer[0x10000]; unsigned long size; + unsigned long offset; } co_win32_overlapped_t; typedef struct start_parameters { @@ -102,27 +103,34 @@ /* Received packet from daemon */ co_message_t *message; char * buffer = overlapped->buffer; - long size_left = overlapped->size; - unsigned long message_size; + long size_left = overlapped->size + overlapped->offset; - do { + while (size_left > 0) { message = (co_message_t *)buffer; - message_size = message->size + sizeof (co_message_t); - buffer += message_size; - size_left -= message_size; - /* Check buffer overrun */ - if (size_left < 0) { - co_debug("Error: Message incomplete (%ld)\n", size_left); - return CO_RC(ERROR); + // Do not dereference message->size unless we have a complete header + if ( (size_left < sizeof (co_message_t)) || + (size_left < (message->size + sizeof (co_message_t))) ) { + // Copy partial message down to bottom of buffer and + // adjust offset so the next read splices the new data + // after the old data + memcpy(overlapped->buffer, buffer, size_left); + overlapped->offset = size_left; + co_debug_lvl(network, 10, "Preserving 0x%x trailing bytes\n", size_left); + return CO_RC(OK); } profile_me("to tap"); + co_debug_lvl(network, 12, "sending to tap (0x%x size 0x%x)\n", message->data, message->size); + /* Send packet using tap. */ co_win32_overlapped_write_async(&tap_overlapped, message->data, message->size); - } while (size_left > 0); + buffer += message->size + sizeof (co_message_t); + size_left -= message->size + sizeof (co_message_t); + } + overlapped->offset = 0; } else { /* Received packet from TAP */ struct { @@ -156,8 +164,8 @@ while (TRUE) { result = ReadFile(overlapped->handle, - &overlapped->buffer, - sizeof(overlapped->buffer), + overlapped->buffer + overlapped->offset, + sizeof(overlapped->buffer) - overlapped->offset, &overlapped->size, &overlapped->read_overlapped); @@ -209,6 +217,7 @@ overlapped->handle = handle; overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); + overlapped->offset = 0; overlapped->read_overlapped.Offset = 0; overlapped->read_overlapped.OffsetHigh = 0; ============================================================ --- src/colinux/os/winnt/user/conet-slirp-daemon/main.c e201c6236a8c99d4fa3624c0b4d6978e850249d3 +++ src/colinux/os/winnt/user/conet-slirp-daemon/main.c 8fafa7e9bd35bc02b6fc5b6034cbe797bfbf7731 @@ -39,6 +39,7 @@ OVERLAPPED write_overlapped; char buffer[0x10000]; unsigned long size; + unsigned long offset; } co_win32_overlapped_t; typedef struct start_parameters { @@ -110,28 +111,36 @@ /* Received packet from daemon */ co_message_t *message; char * buffer = overlapped->buffer; - long size_left = overlapped->size; - unsigned long message_size; + long size_left = overlapped->size + overlapped->offset; - do { + while (size_left > 0) { message = (co_message_t *)buffer; - message_size = message->size + sizeof (co_message_t); - buffer += message_size; - size_left -= message_size; - /* Check buffer overrun */ - if (size_left < 0) { - co_debug("Error: Message incomplete (%ld)\n", size_left); - return CO_RC(ERROR); + // Do not dereference message->size unless we have a complete header + if ( (size_left < sizeof (co_message_t)) || + (size_left < (message->size + sizeof (co_message_t))) ) { + // Copy partial message down to bottom of buffer and + // adjust offset so the next read splices the new data + // after the old data + memcpy(overlapped->buffer, buffer, size_left); + overlapped->offset = size_left; + co_debug_lvl(network, 10, "Preserving 0x%x trailing bytes\n", size_left); + return CO_RC(OK); } profile_me("to slirp"); + co_debug_lvl(network, 12, "sending to slirp (0x%x size 0x%x)\n", message->data, message->size); + /* Send packet using slirp. */ WaitForSingleObject(slirp_mutex, INFINITE); slirp_input(message->data, message->size); ReleaseMutex(slirp_mutex); - } while (size_left > 0); + buffer += message->size + sizeof (co_message_t); + size_left -= message->size + sizeof (co_message_t); + } + + overlapped->offset = 0; } return CO_RC(OK); @@ -144,8 +153,8 @@ while (TRUE) { result = ReadFile(overlapped->handle, - &overlapped->buffer, - sizeof(overlapped->buffer), + overlapped->buffer + overlapped->offset, + sizeof(overlapped->buffer) - overlapped->offset, &overlapped->size, &overlapped->read_overlapped); @@ -197,6 +206,7 @@ overlapped->handle = handle; overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); + overlapped->offset = 0; overlapped->read_overlapped.Offset = 0; overlapped->read_overlapped.OffsetHigh = 0; ============================================================ --- src/colinux/os/winnt/user/coserial-daemon/main.c a534e263449c4fb1d9cc22c0429b902143b47503 +++ src/colinux/os/winnt/user/coserial-daemon/main.c c5e821921987cb0ea329bf687c17424dfc49faa5 @@ -34,6 +34,7 @@ OVERLAPPED write_overlapped; char buffer[0x10000]; unsigned long size; + unsigned long offset; } co_win32_overlapped_t; typedef struct start_parameters { @@ -79,25 +80,31 @@ /* Received packet from daemon */ co_message_t *message; char * buffer = overlapped->buffer; - long size_left = overlapped->size; - unsigned long message_size; + long size_left = overlapped->size + overlapped->offset; - do { + while (size_left > 0) { message = (co_message_t *)buffer; - message_size = message->size + sizeof (co_message_t); - buffer += message_size; - size_left -= message_size; - /* Check buffer overrun */ - if (size_left < 0) { - co_debug("Error: Message incomplete (%ld)\n", size_left); - return CO_RC(ERROR); + // Do not dereference message->size unless we have a complete header + if ( (size_left < sizeof (co_message_t)) || + (size_left < (message->size + sizeof (co_message_t))) ) { + // Copy partial message down to bottom of buffer and + // adjust offset so the next read splices the new data + // after the old data + memcpy(overlapped->buffer, buffer, size_left); + overlapped->offset = size_left; + co_debug("Preserving 0x%x trailing bytes\n", size_left); + return CO_RC(OK); } + /* Send packet using serial deamon. */ co_win32_overlapped_write_async(&stdio_overlapped, message->data, message->size); + buffer += message->size + sizeof (co_message_t); + size_left -= message->size + sizeof (co_message_t); } while (size_left > 0); + overlapped->offset = 0; } else { /* Received packet from standard input */ struct { @@ -129,8 +136,8 @@ while (TRUE) { result = ReadFile(overlapped->read_handle, - &overlapped->buffer, - sizeof(overlapped->buffer), + overlapped->buffer + overlapped->offset, + sizeof(overlapped->buffer) - overlapped->offset, &overlapped->size, &overlapped->read_overlapped); @@ -183,6 +190,7 @@ overlapped->write_handle = write_handle; overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); + overlapped->offset = 0; overlapped->read_overlapped.Offset = 0; overlapped->read_overlapped.OffsetHigh = 0;