⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne2000-bounds-checks

📁 xen虚拟机源代码安装包
💻
字号:
# HG changeset patch# User kaf24@localhost.localdomain# Node ID 66fe61db9e69e03e12d0c4086683bebfb4a67780# Parent  1940ee13f9d6ab1be2c614a0fbf7769536a056d2[QEMU] ne2000: Stop memory access beyond bufferAs a program that runs in dom0 which serves users from guests,the qemu drivers need to be vigilant to the input that comesfrom the guests since they may be malicious.As it is there are multiple ways to get ne2000 to read/writememory beyond the 48K buffer that it has allocated for eachadapter.This patch checks the addresses and prevents this from occuring.The boundary is checked each time since it's changed for everypacket received while the other parameters are only changed(by the guest) during setup.Signed-off: Herbert Xu <herbert@gondor.apana.org.au>Index: ioemu/hw/ne2000.c===================================================================--- ioemu.orig/hw/ne2000.c	2007-05-03 19:30:23.000000000 +0100+++ ioemu/hw/ne2000.c	2007-05-03 20:38:52.000000000 +0100@@ -137,6 +137,7 @@     uint8_t curpag;     uint8_t mult[8]; /* multicast mask array */     int irq;+    int tainted;     PCIDevice *pci_dev;     VLANClientState *vc;     uint8_t macaddr[6];@@ -226,6 +227,27 @@  #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;@@ -239,6 +261,12 @@     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;     @@ -359,9 +387,11 @@         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 +436,7 @@             break;         case EN1_CURPAG:             s->curpag = val;+            s->tainted = 1;             break;         case EN1_MULT ... EN1_MULT + 7:             s->mult[offset - EN1_MULT] = val;@@ -509,7 +540,7 @@ {     addr &= ~1; /* XXX: check exact behaviour if not even */     if (addr < 32 || -        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {+        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) {         cpu_to_le32wu((uint32_t *)(s->mem + addr), val);     } }@@ -539,7 +570,7 @@ {     addr &= ~1; /* XXX: check exact behaviour if not even */     if (addr < 32 || -        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {+        (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE - 2)) {         return le32_to_cpupu((uint32_t *)(s->mem + addr));     } else {         return 0xffffffff;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -