From 3941282f84ee51fe9646fb832527e64181a56f24 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 7 May 2008 16:20:46 +0100 Subject: [PATCH] merge from in xen-unstable tip (17318:b5fea3aeb04b): hw/ne2000: security fixes and ability to load/save multiple NICs --- hw/ne2000.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/hw/ne2000.c b/hw/ne2000.c index 2ae140859..760c1e691 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -140,6 +140,7 @@ typedef struct NE2000State { uint8_t curpag; uint8_t mult[8]; /* multicast mask array */ qemu_irq irq; + int tainted; PCIDevice *pci_dev; VLANClientState *vc; uint8_t macaddr[6]; @@ -223,6 +224,27 @@ static int ne2000_can_receive(void *opaque) #define MIN_BUF_SIZE 60 +static inline int ne2000_valid_ring_addr(NE2000State *s, unsigned int addr) +{ + addr <<= 8; + return addr < s->stop && addr >= s->start; +} + +static inline int ne2000_check_state(NE2000State *s) +{ + if (!s->tainted) + return 0; + + if (s->start >= s->stop || s->stop > NE2000_MEM_SIZE) + return -EINVAL; + + if (!ne2000_valid_ring_addr(s, s->curpag)) + return -EINVAL; + + s->tainted = 0; + return 0; +} + static void ne2000_receive(void *opaque, const uint8_t *buf, int size) { NE2000State *s = opaque; @@ -236,6 +258,12 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size) printf("NE2000: received len=%d\n", size); #endif + if (ne2000_check_state(s)) + return; + + if (!ne2000_valid_ring_addr(s, s->boundary)) + return; + if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) return; @@ -296,6 +324,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size) /* write packet data */ while (size > 0) { + /* taviso: this can wrap, so check its okay. */ if (index <= s->stop) avail = s->stop - index; else @@ -359,9 +388,11 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) switch(offset) { case EN0_STARTPG: s->start = val << 8; + s->tainted = 1; break; case EN0_STOPPG: s->stop = val << 8; + s->tainted = 1; break; case EN0_BOUNDARY: s->boundary = val; @@ -406,6 +437,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case EN1_CURPAG: s->curpag = val; + s->tainted = 1; break; case EN1_MULT ... EN1_MULT + 7: s->mult[offset - EN1_MULT] = val; @@ -508,8 +540,8 @@ static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, uint32_t val) { addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) { cpu_to_le32wu((uint32_t *)(s->mem + addr), val); } } @@ -538,8 +570,8 @@ static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr) static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr) { addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) { return le32_to_cpupu((uint32_t *)(s->mem + addr)); } else { return 0xffffffff; @@ -752,8 +784,8 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) s->macaddr[3], s->macaddr[4], s->macaddr[5]); - - register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + + register_savevm("ne2000", base, 2, ne2000_save, ne2000_load, s); } /***********************************************************/ -- 2.39.5