summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-02-04 22:15:28 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-02-04 22:15:28 +0000
commitd861b05ea30e6ac177de9b679da96194ebe21afc (patch)
tree6bb3605e24633c0e64c9b7396873bbe28fe93be1 /hw
parent191abaa2f0aca0c6ebca06f3e985da02ac950d14 (diff)
downloadfocaccia-qemu-d861b05ea30e6ac177de9b679da96194ebe21afc.tar.gz
focaccia-qemu-d861b05ea30e6ac177de9b679da96194ebe21afc.zip
Avoid buffer overflow when sending slirp packets.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1744 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r--hw/lance.c7
-rw-r--r--hw/ne2000.c29
-rw-r--r--hw/smc91c111.c14
3 files changed, 37 insertions, 13 deletions
diff --git a/hw/lance.c b/hw/lance.c
index 2fef6b1eb0..c0cb0f98d6 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -283,6 +283,11 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
 
 #define MIN_BUF_SIZE 60
 
+static void lance_can_receive(void *opaque)
+{
+    return 1;
+}
+
 static void lance_receive(void *opaque, const uint8_t *buf, int size)
 {
     LANCEState *s = opaque;
@@ -440,7 +445,7 @@ void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
 
     lance_reset(s);
 
-    s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
diff --git a/hw/ne2000.c b/hw/ne2000.c
index efc3ea8ece..674d83e490 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -200,14 +200,10 @@ static int compute_mcast_idx(const uint8_t *ep)
     return (crc >> 26);
 }
 
-/* return the max buffer size if the NE2000 can receive more data */
-static int ne2000_can_receive(void *opaque)
+static int ne2000_buffer_full(NE2000State *s)
 {
-    NE2000State *s = opaque;
     int avail, index, boundary;
-    
-    if (s->cmd & E8390_STOP)
-        return 0;
+
     index = s->curpag << 8;
     boundary = s->boundary << 8;
     if (index < boundary)
@@ -215,8 +211,17 @@ static int ne2000_can_receive(void *opaque)
     else
         avail = (s->stop - s->start) - (index - boundary);
     if (avail < (MAX_ETH_FRAME_SIZE + 4))
-        return 0;
-    return MAX_ETH_FRAME_SIZE;
+        return 1;
+    return 0;
+}
+
+static int ne2000_can_receive(void *opaque)
+{
+    NE2000State *s = opaque;
+    
+    if (s->cmd & E8390_STOP)
+        return 1;
+    return !ne2000_buffer_full(s);
 }
 
 #define MIN_BUF_SIZE 60
@@ -234,7 +239,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
     printf("NE2000: received len=%d\n", size);
 #endif
 
-    if (!ne2000_can_receive(s))
+    if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
         return;
     
     /* XXX: check this */
@@ -722,7 +727,8 @@ void isa_ne2000_init(int base, int irq, NICInfo *nd)
 
     ne2000_reset(s);
 
-    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
+                                 ne2000_can_receive, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
@@ -791,7 +797,8 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
     s->pci_dev = (PCIDevice *)d;
     memcpy(s->macaddr, nd->macaddr, 6);
     ne2000_reset(s);
-    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
+                                 ne2000_can_receive, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 375debd1fc..214e92efc0 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -593,6 +593,17 @@ static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset)
     return val;
 }
 
+static int smc91c111_can_receive(void *opaque)
+{
+    smc91c111_state *s = (smc91c111_state *)opaque;
+
+    if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
+        return 1;
+    if (s->allocated == (1 << NUM_PACKETS) - 1)
+        return 0;
+    return 1;
+}
+
 static void smc91c111_receive(void *opaque, const uint8_t *buf, int size)
 {
     smc91c111_state *s = (smc91c111_state *)opaque;
@@ -697,6 +708,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)
 
     smc91c111_reset(s);
 
-    s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive,
+                                 smc91c111_can_receive, s);
     /* ??? Save/restore.  */
 }