Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 337

kvm-83-270.el5_11.src.rpm

From a7ff01fa85020e8a6b33458082586353fb3e75db Mon Sep 17 00:00:00 2001
From: Michael S. Tsirkin <mst@redhat.com>
Date: Thu, 17 Mar 2011 07:26:01 -0300
Subject: [PATCH 01/10] eepro100: Don't allow guests to fail assertions

RH-Author: Michael S. Tsirkin <mst@redhat.com>
Message-id: <20110317072549.GA6416@redhat.com>
Patchwork-id: 20173
O-Subject: [PATCH 5.7] eepro100: Don't allow guests to fail assertions
Bugzilla: 550273
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

Author: Kevin Wolf <kwolf@redhat.com>
eepro100: Don't allow guests to fail assertions

The idea of using assert() for input validation is rather questionable.
Let's remove it from eepro100, so that guests need to find more
interesting
ways if they want to crash qemu.

This patch replaces asserts that are directly dependent on
guest-accessible
data by other means of error handling.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

Upstream: 7f1e9d4e138f5baf1e862a1221ba13eee7dcce9e
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=550273

Couldn't reproduce the problem in bz but the cause seems
clear enough. Patch is tested, seems to be fine and it seems unlikely
this can break anything.

---
 qemu/hw/eepro100.c |   49 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 36 insertions(+), 13 deletions(-)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qemu/hw/eepro100.c |   49 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/qemu/hw/eepro100.c b/qemu/hw/eepro100.c
index d9df755..dc91c04 100644
--- a/qemu/hw/eepro100.c
+++ b/qemu/hw/eepro100.c
@@ -38,6 +38,7 @@
 # warning "PXE boot still not working!"
 #endif
 
+#include <stdbool.h>
 #include <assert.h>
 #include <stddef.h>             /* offsetof */
 #include "hw.h"
@@ -87,7 +88,7 @@
 
 #define TRACE(flag, command) ((flag) ? (command) : (void)0)
 
-#define missing(text)       assert(!"feature is missing in this emulation: " text)
+#define missing(text) fprintf(stderr, "eepro100: feature is missing in this emulation: " text "\n")
 
 #define MAX_ETH_FRAME_SIZE 1514
 
@@ -128,8 +129,6 @@
 #define INT_MASK        0x0100
 #define DRVR_INT        0x0200  /* Driver generated interrupt. */
 
-typedef unsigned char bool;
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
@@ -690,6 +689,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
         bool bit_s = ((command & 0x4000) != 0);
         bool bit_i = ((command & 0x2000) != 0);
         bool bit_nc = ((command & 0x0010) != 0);
+        bool success = true;
         //~ bool bit_sf = ((command & 0x0008) != 0);
         uint16_t cmd = command & 0x0007;
         s->cu_offset = le32_to_cpu(tx.link);
@@ -716,9 +716,17 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
             logout
                 ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
                  tbd_array, tcb_bytes, tx.tbd_count);
-            assert(!bit_nc);
+
+            if (bit_nc) {
+                missing("CmdTx: NC = 0");
+                success = false;
+                break;
+            }
             //~ assert(!bit_sf);
-            assert(tcb_bytes <= 2600);
+            if (tcb_bytes > 2600) {
+                logout("TCB byte count too large, using 2600\n");
+                tcb_bytes = 2600;
+            }
             /* Next assertion fails for local configuration. */
             //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
             if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
@@ -750,7 +758,6 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
                 uint8_t tbd_count = 0;
                 if (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) {
                     /* Extended Flexible TCB. */
-                    assert(tcb_bytes == 0);
                     for (; tbd_count < 2; tbd_count++) {
                         uint32_t tx_buffer_address = ldl_phys(tbd_address);
                         uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
@@ -799,9 +806,11 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
             break;
         default:
             missing("undefined command");
+            success = false;
+            break;
         }
-        /* Write new status (success). */
-        stw_phys(cb_address, status | 0x8000 | 0x2000);
+        /* Write new status. */
+        stw_phys(cb_address, status | 0x8000 | (success ? 0x2000 : 0));
         if (bit_i) {
             /* CU completed action. */
             eepro100_cx_interrupt(s);
@@ -1489,7 +1498,10 @@ static void nic_receive(void *opaque, const uint8_t * buf, int size)
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
     /* TODO: check multiple IA bit. */
-    assert(!(s->configuration[20] & BIT(6)));
+    if (s->configuration[20] & BIT(6)) {
+        missing("Multiple IA bit");
+        return;
+    }
 
     if (s->configuration[8] & 0x80) {
         /* CSMA is disabled. */
@@ -1518,7 +1530,9 @@ static void nic_receive(void *opaque, const uint8_t * buf, int size)
         /* Multicast frame. */
         logout("%p received multicast, len=%d\n", s, size);
         /* TODO: check multicast all bit. */
-        assert(!(s->configuration[21] & BIT(3)));
+        if (s->configuration[21] & BIT(3)) {
+            missing("Multicast All bit");
+        }
         int mcast_idx = compute_mcast_idx(buf);
         if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) {
             return;
@@ -1548,7 +1562,12 @@ static void nic_receive(void *opaque, const uint8_t * buf, int size)
                              offsetof(eepro100_rx_t, packet));
     uint16_t rfd_command = le16_to_cpu(rx.command);
     uint16_t rfd_size = le16_to_cpu(rx.size);
-    assert(size <= rfd_size);
+
+    if (size > rfd_size) {
+        logout("Receive buffer (%" PRId16 " bytes) too small for data "
+            "(%zu bytes); data truncated\n", rfd_size, size);
+        size = rfd_size;
+    }
     if (size < 64) {
         rfd_status |= 0x0080;
     }
@@ -1560,7 +1579,10 @@ static void nic_receive(void *opaque, const uint8_t * buf, int size)
     /* Early receive interrupt not supported. */
     //~ eepro100_er_interrupt(s);
     /* Receive CRC Transfer not supported. */
-    assert(!(s->configuration[18] & 4));
+    if (s->configuration[18] & 4) {
+        missing("Receive CRC Transfer");
+        return;
+    }
     /* TODO: check stripping enable bit. */
     //~ assert(!(s->configuration[17] & 1));
     cpu_physical_memory_write(s->ru_base + s->ru_offset +
@@ -1570,7 +1592,8 @@ static void nic_receive(void *opaque, const uint8_t * buf, int size)
     s->ru_offset = le32_to_cpu(rx.link);
     if (rfd_command & 0x8000) {
         /* EL bit is set, so this was the last frame. */
-        assert(0);
+        logout("receive: Running out of frames\n");
+        set_ru_state(s, ru_suspended);
     }
     if (rfd_command & 0x4000) {
         /* S bit is set. */
-- 
1.7.5.141.g791a