* [Qemu-devel] [PULL for-2.5 1/3] eepro100: Prevent two endless loops
2015-11-27 3:12 [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Jason Wang
@ 2015-11-27 3:12 ` Jason Wang
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 2/3] tap-win32: skip unexpected nodes during registry enumeration Jason Wang
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jason Wang @ 2015-11-27 3:12 UTC (permalink / raw)
To: qemu-devel, peter.maydell; +Cc: Stefan Weil, Jason Wang
From: Stefan Weil <sw@weilnetz.de>
http://lists.nongnu.org/archive/html/qemu-devel/2015-11/msg04592.html
shows an example how an endless loop in function action_command can
be achieved.
During my code review, I noticed a 2nd case which can result in an
endless loop.
Reported-by: Qinghao Tang <luodalongde@gmail.com>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/net/eepro100.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 60333b7..685a478 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -774,6 +774,11 @@ static void tx_command(EEPRO100State *s)
#if 0
uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
#endif
+ if (tx_buffer_size == 0) {
+ /* Prevent an endless loop. */
+ logout("loop in %s:%u\n", __FILE__, __LINE__);
+ break;
+ }
tbd_address += 8;
TRACE(RXTX, logout
("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
@@ -855,6 +860,10 @@ static void set_multicast_list(EEPRO100State *s)
static void action_command(EEPRO100State *s)
{
+ /* The loop below won't stop if it gets special handcrafted data.
+ Therefore we limit the number of iterations. */
+ unsigned max_loop_count = 16;
+
for (;;) {
bool bit_el;
bool bit_s;
@@ -870,6 +879,13 @@ static void action_command(EEPRO100State *s)
#if 0
bool bit_sf = ((s->tx.command & COMMAND_SF) != 0);
#endif
+
+ if (max_loop_count-- == 0) {
+ /* Prevent an endless loop. */
+ logout("loop in %s:%u\n", __FILE__, __LINE__);
+ break;
+ }
+
s->cu_offset = s->tx.link;
TRACE(OTHER,
logout("val=(cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
--
2.5.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [Qemu-devel] [PULL for-2.5 2/3] tap-win32: skip unexpected nodes during registry enumeration
2015-11-27 3:12 [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Jason Wang
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 1/3] eepro100: Prevent two endless loops Jason Wang
@ 2015-11-27 3:12 ` Jason Wang
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 3/3] tap-win32: disable broken async write path Jason Wang
2015-11-27 11:30 ` [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Peter Maydell
3 siblings, 0 replies; 5+ messages in thread
From: Jason Wang @ 2015-11-27 3:12 UTC (permalink / raw)
To: qemu-devel, peter.maydell; +Cc: Jason Wang, Andrew Baumann
From: Andrew Baumann <Andrew.Baumann@microsoft.com>
In order to find a named tap device, get_device_guid() enumerates children of
HKLM\SYSTEM\CCS\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}
(aka NETWORK_CONNECTIONS_KEY). For each child, it then looks for a
"Connection" subkey, but if this key doesn't exist, it aborts the
entire search. This was observed to fail on at least one Windows 10
machine, where there is an additional child of NETWORK_CONNECTIONS_KEY
(named "Descriptions"). Since registry enumeration doesn't guarantee
any particular sort order, we should continue to search for matching
children rather than aborting the search.
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/tap-win32.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 4e2fa55..5e5d6db 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -356,7 +356,8 @@ static int get_device_guid(
&len);
if (status != ERROR_SUCCESS || name_type != REG_SZ) {
- return -1;
+ ++i;
+ continue;
}
else {
if (is_tap_win32_dev(enum_name)) {
--
2.5.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [Qemu-devel] [PULL for-2.5 3/3] tap-win32: disable broken async write path
2015-11-27 3:12 [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Jason Wang
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 1/3] eepro100: Prevent two endless loops Jason Wang
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 2/3] tap-win32: skip unexpected nodes during registry enumeration Jason Wang
@ 2015-11-27 3:12 ` Jason Wang
2015-11-27 11:30 ` [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Peter Maydell
3 siblings, 0 replies; 5+ messages in thread
From: Jason Wang @ 2015-11-27 3:12 UTC (permalink / raw)
To: qemu-devel, peter.maydell; +Cc: Jason Wang, Andrew Baumann
From: Andrew Baumann <Andrew.Baumann@microsoft.com>
The code under the TUN_ASYNCHRONOUS_WRITES path makes two incorrect
assumptions about the behaviour of the WriteFile API for overlapped
file handles. First, WriteFile does not update the
lpNumberOfBytesWritten parameter when the write completes
asynchronously (the number of bytes written is known only when the
operation completes). Second, the buffer shouldn't be touched (or
freed) until the operation completes. This led to at least one bug
where tap_win32_write returned zero bytes written, which in turn
caused further writes ("receives") to be disabled for that device.
This change disables the asynchronous write path, while keeping most
of the code around in case someone sees value in resurrecting it. It
also adds some conditional debug output, similar to the read path.
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Acked-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/tap-win32.c | 46 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 36 insertions(+), 10 deletions(-)
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 5e5d6db..7fddb20 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -77,7 +77,12 @@
//#define DEBUG_TAP_WIN32
-#define TUN_ASYNCHRONOUS_WRITES 1
+/* FIXME: The asynch write path appears to be broken at
+ * present. WriteFile() ignores the lpNumberOfBytesWritten parameter
+ * for overlapped writes, with the result we return zero bytes sent,
+ * and after handling a single packet, receive is disabled for this
+ * interface. */
+/* #define TUN_ASYNCHRONOUS_WRITES 1 */
#define TUN_BUFFER_SIZE 1560
#define TUN_MAX_BUFFER_COUNT 32
@@ -461,27 +466,48 @@ static int tap_win32_write(tap_win32_overlapped_t *overlapped,
BOOL result;
DWORD error;
+#ifdef TUN_ASYNCHRONOUS_WRITES
result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
&write_size, FALSE);
if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
WaitForSingleObject(overlapped->write_event, INFINITE);
+#endif
result = WriteFile(overlapped->handle, buffer, size,
&write_size, &overlapped->write_overlapped);
+#ifdef TUN_ASYNCHRONOUS_WRITES
+ /* FIXME: we can't sensibly set write_size here, without waiting
+ * for the IO to complete! Moreover, we can't return zero,
+ * because that will disable receive on this interface, and we
+ * also can't assume it will succeed and return the full size,
+ * because that will result in the buffer being reclaimed while
+ * the IO is in progress. */
+#error Async writes are broken. Please disable TUN_ASYNCHRONOUS_WRITES.
+#else /* !TUN_ASYNCHRONOUS_WRITES */
if (!result) {
- switch (error = GetLastError())
- {
- case ERROR_IO_PENDING:
-#ifndef TUN_ASYNCHRONOUS_WRITES
- WaitForSingleObject(overlapped->write_event, INFINITE);
-#endif
- break;
- default:
- return -1;
+ error = GetLastError();
+ if (error == ERROR_IO_PENDING) {
+ result = GetOverlappedResult(overlapped->handle,
+ &overlapped->write_overlapped,
+ &write_size, TRUE);
}
}
+#endif
+
+ if (!result) {
+#ifdef DEBUG_TAP_WIN32
+ LPTSTR msgbuf;
+ error = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ &msgbuf, 0, NULL);
+ fprintf(stderr, "Tap-Win32: Error WriteFile %d - %s\n", error, msgbuf);
+ LocalFree(msgbuf);
+#endif
+ return 0;
+ }
return write_size;
}
--
2.5.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5
2015-11-27 3:12 [Qemu-devel] [PULL for-2.5 0/3] Net patches for 2.5 Jason Wang
` (2 preceding siblings ...)
2015-11-27 3:12 ` [Qemu-devel] [PULL for-2.5 3/3] tap-win32: disable broken async write path Jason Wang
@ 2015-11-27 11:30 ` Peter Maydell
3 siblings, 0 replies; 5+ messages in thread
From: Peter Maydell @ 2015-11-27 11:30 UTC (permalink / raw)
To: Jason Wang; +Cc: QEMU Developers
On 27 November 2015 at 03:12, Jason Wang <jasowang@redhat.com> wrote:
> The following changes since commit b04fc428356a540fdb9065fa8c3c71ee476c2031:
>
> Update version for v2.5.0-rc2 release (2015-11-26 17:50:12 +0000)
>
> are available in the git repository at:
>
> https://github.com/jasowang/qemu.git tags/net-pull-request
>
> for you to fetch changes up to b73c1849148da1229a3c3b336311a8194970b35f:
>
> tap-win32: disable broken async write path (2015-11-27 10:39:55 +0800)
>
> ----------------------------------------------------------------
>
> ----------------------------------------------------------------
> Andrew Baumann (2):
> tap-win32: skip unexpected nodes during registry enumeration
> tap-win32: disable broken async write path
>
> Stefan Weil (1):
> eepro100: Prevent two endless loops
>
> hw/net/eepro100.c | 16 ++++++++++++++++
> net/tap-win32.c | 49 ++++++++++++++++++++++++++++++++++++++-----------
> 2 files changed, 54 insertions(+), 11 deletions(-)
Applied, thanks.
-- PMM
^ permalink raw reply [flat|nested] 5+ messages in thread