diff --git a/CVE-2016-1981-qemut-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch b/CVE-2016-1981-qemut-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch new file mode 100644 index 0000000..5e0f191 --- /dev/null +++ b/CVE-2016-1981-qemut-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch @@ -0,0 +1,94 @@ +The start_xmit() and e1000_receive_iov() functions implement DMA transfers +iterating over a set of descriptors that the guest's e1000 driver +prepares: + +- the TDLEN and RDLEN registers store the total size of the descriptor + area, + +- while the TDH and RDH registers store the offset (in whole tx / rx + descriptors) into the area where the transfer is supposed to start. + +Each time a descriptor is processed, the TDH and RDH register is bumped +(as appropriate for the transfer direction). + +QEMU already contains logic to deal with bogus transfers submitted by the +guest: + +- Normally, the transmit case wants to increase TDH from its initial value + to TDT. (TDT is allowed to be numerically smaller than the initial TDH + value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe + that QEMU currently has here is a check against reaching the original + TDH value again -- a complete wraparound, which should never happen. + +- In the receive case RDH is increased from its initial value until + "total_size" bytes have been received; preferably in a single step, or + in "s->rxbuf_size" byte steps, if the latter is smaller. However, null + RX descriptors are skipped without receiving data, while RDH is + incremented just the same. QEMU tries to prevent an infinite loop + (processing only null RX descriptors) by detecting whether RDH assumes + its original value during the loop. (Again, wrapping from RDLEN to 0 is + normal.) + +What both directions miss is that the guest could program TDLEN and RDLEN +so low, and the initial TDH and RDH so high, that these registers will +immediately be truncated to zero, and then never reassume their initial +values in the loop -- a full wraparound will never occur. + +The condition that expresses this is: + + xdh_start >= s->mac_reg[XDLEN] / sizeof(desc) + +i.e., TDH or RDH start out after the last whole rx or tx descriptor that +fits into the TDLEN or RDLEN sized area. + +This condition could be checked before we enter the loops, but +pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for +bogus DMA addresses, so we just extend the existing failsafes with the +above condition. + +Cc: "Michael S. Tsirkin"
+Cc: Petr Matousek +Cc: Stefano Stabellini +Cc: Prasad Pandit +Cc: Michael Roth +Cc: Jason Wang +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044 +Signed-off-by: Laszlo Ersek +Reviewed-by: Jason Wang +--- + +Notes: + Regarding the public posting: we made an honest effort to vet this + vulnerability, and the impact seems low -- no host side reads/writes, + "just" a DoS (infinite loop). We decided the patch could be posted + publicly, for the usual review process. Jason and Prasad checked the + patch in the internal discussion already, but comments, improvements + etc. are clearly welcome. The CVE request is underway. Thanks. + + hw/net/e1000.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +Index: xen-4.6.0-testing/tools/qemu-xen-traditional-dir-remote/hw/e1000.c +=================================================================== +--- xen-4.6.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/e1000.c ++++ xen-4.6.0-testing/tools/qemu-xen-traditional-dir-remote/hw/e1000.c +@@ -537,7 +537,8 @@ start_xmit(E1000State *s) + * bogus values to TDT/TDLEN. + * there's nothing too intelligent we could do about this. + */ +- if (s->mac_reg[TDH] == tdh_start) { ++ if (s->mac_reg[TDH] == tdh_start || ++ tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) { + DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", + tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); + break; +@@ -727,7 +728,8 @@ e1000_receive(void *opaque, const uint8_ + s->mac_reg[RDH] = 0; + s->check_rxov = 1; + /* see comment in start_xmit; same here */ +- if (s->mac_reg[RDH] == rdh_start) { ++ if (s->mac_reg[RDH] == rdh_start || ++ rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) { + DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", + rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); + set_ics(s, 0, E1000_ICS_RXO); diff --git a/CVE-2016-1981-qemuu-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch b/CVE-2016-1981-qemuu-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch new file mode 100644 index 0000000..bb2d829 --- /dev/null +++ b/CVE-2016-1981-qemuu-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch @@ -0,0 +1,94 @@ +The start_xmit() and e1000_receive_iov() functions implement DMA transfers +iterating over a set of descriptors that the guest's e1000 driver +prepares: + +- the TDLEN and RDLEN registers store the total size of the descriptor + area, + +- while the TDH and RDH registers store the offset (in whole tx / rx + descriptors) into the area where the transfer is supposed to start. + +Each time a descriptor is processed, the TDH and RDH register is bumped +(as appropriate for the transfer direction). + +QEMU already contains logic to deal with bogus transfers submitted by the +guest: + +- Normally, the transmit case wants to increase TDH from its initial value + to TDT. (TDT is allowed to be numerically smaller than the initial TDH + value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe + that QEMU currently has here is a check against reaching the original + TDH value again -- a complete wraparound, which should never happen. + +- In the receive case RDH is increased from its initial value until + "total_size" bytes have been received; preferably in a single step, or + in "s->rxbuf_size" byte steps, if the latter is smaller. However, null + RX descriptors are skipped without receiving data, while RDH is + incremented just the same. QEMU tries to prevent an infinite loop + (processing only null RX descriptors) by detecting whether RDH assumes + its original value during the loop. (Again, wrapping from RDLEN to 0 is + normal.) + +What both directions miss is that the guest could program TDLEN and RDLEN +so low, and the initial TDH and RDH so high, that these registers will +immediately be truncated to zero, and then never reassume their initial +values in the loop -- a full wraparound will never occur. + +The condition that expresses this is: + + xdh_start >= s->mac_reg[XDLEN] / sizeof(desc) + +i.e., TDH or RDH start out after the last whole rx or tx descriptor that +fits into the TDLEN or RDLEN sized area. + +This condition could be checked before we enter the loops, but +pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for +bogus DMA addresses, so we just extend the existing failsafes with the +above condition. + +Cc: "Michael S. Tsirkin" +Cc: Petr Matousek +Cc: Stefano Stabellini +Cc: Prasad Pandit +Cc: Michael Roth +Cc: Jason Wang +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044 +Signed-off-by: Laszlo Ersek +Reviewed-by: Jason Wang +--- + +Notes: + Regarding the public posting: we made an honest effort to vet this + vulnerability, and the impact seems low -- no host side reads/writes, + "just" a DoS (infinite loop). We decided the patch could be posted + publicly, for the usual review process. Jason and Prasad checked the + patch in the internal discussion already, but comments, improvements + etc. are clearly welcome. The CVE request is underway. Thanks. + + hw/net/e1000.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +Index: xen-4.6.0-testing/tools/qemu-xen-dir-remote/hw/net/e1000.c +=================================================================== +--- xen-4.6.0-testing.orig/tools/qemu-xen-dir-remote/hw/net/e1000.c ++++ xen-4.6.0-testing/tools/qemu-xen-dir-remote/hw/net/e1000.c +@@ -815,7 +815,8 @@ start_xmit(E1000State *s) + * bogus values to TDT/TDLEN. + * there's nothing too intelligent we could do about this. + */ +- if (s->mac_reg[TDH] == tdh_start) { ++ if (s->mac_reg[TDH] == tdh_start || ++ tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) { + DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n", + tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]); + break; +@@ -1059,7 +1060,8 @@ e1000_receive_iov(NetClientState *nc, co + if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) + s->mac_reg[RDH] = 0; + /* see comment in start_xmit; same here */ +- if (s->mac_reg[RDH] == rdh_start) { ++ if (s->mac_reg[RDH] == rdh_start || ++ rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) { + DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n", + rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]); + set_ics(s, 0, E1000_ICS_RXO); diff --git a/xen.changes b/xen.changes index 04d563e..6b75057 100644 --- a/xen.changes +++ b/xen.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Wed Jan 27 08:23:26 MST 2016 - carnold@suse.com + +- bsc#963783 - VUL-1: CVE-2016-1981: xen: net: e1000 infinite loop + in start_xmit and e1000_receive_iov routines + CVE-2016-1981-qemuu-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch + CVE-2016-1981-qemut-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch + ------------------------------------------------------------------- Wed Jan 20 08:21:42 MST 2016 - carnold@suse.com diff --git a/xen.spec b/xen.spec index 5702381..6eba739 100644 --- a/xen.spec +++ b/xen.spec @@ -1,7 +1,7 @@ # # spec file for package xen # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -15,7 +15,6 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # - # needssslcertforbuild Name: xen @@ -277,6 +276,8 @@ Patch281: CVE-2013-4537-qemut-ssi-sd-fix-buffer-overrun-on-invalid-state-l Patch282: CVE-2015-1779-qemuu-incrementally-decode-websocket-frames.patch Patch283: CVE-2015-1779-qemuu-limit-size-of-HTTP-headers-from-websockets-clients.patch Patch284: CVE-2013-4539-qemut-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch +Patch285: CVE-2016-1981-qemuu-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch +Patch286: CVE-2016-1981-qemut-e1000-eliminate-infinite-loops-on-out-of-bounds-transfer.patch # Our platform specific patches Patch321: xen-destdir.patch Patch322: vif-bridge-no-iptables.patch @@ -620,6 +621,8 @@ Authors: %patch282 -p1 %patch283 -p1 %patch284 -p1 +%patch285 -p1 +%patch286 -p1 # Our platform specific patches %patch321 -p1 %patch322 -p1