- bsc#939712 - VUL-0: XSA-140: QEMU leak of uninitialized heap
memory in rtl8139 device model xsa140-qemuu-1.patch xsa140-qemuu-2.patch xsa140-qemuu-3.patch xsa140-qemuu-4.patch xsa140-qemuu-5.patch xsa140-qemuu-6.patch xsa140-qemuu-7.patch xsa140-qemut-1.patch xsa140-qemut-2.patch xsa140-qemut-3.patch xsa140-qemut-4.patch xsa140-qemut-5.patch xsa140-qemut-6.patch xsa140-qemut-7.patch - bsc#939709 - VUL-0: XSA-139: xen: Use after free in QEMU/Xen block unplug protocol xsa139-qemuu.patch - bsc#937371 - xen vm's running after reboot xendomains-libvirtd-conflict.patch - bsc#938344 - VUL-0: CVE-2015-5154: qemu,kvm,xen: host code execution via IDE subsystem CD-ROM CVE-2015-5154-qemuu-check-array-bounds-before-writing-to-io_buffer.patch CVE-2015-5154-qemut-check-array-bounds-before-writing-to-io_buffer.patch CVE-2015-5154-qemuu-fix-START-STOP-UNIT-command-completion.patch CVE-2015-5154-qemut-fix-START-STOP-UNIT-command-completion.patch CVE-2015-5154-qemuu-clear-DRQ-after-handling-all-expected-accesses.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=371
This commit is contained in:
parent
763b78040d
commit
b5fb5e90fb
@ -0,0 +1,74 @@
|
|||||||
|
From a9de14175548c04e0f8be7fae219246509ba46a9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:13:31 +0200
|
||||||
|
Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
|
||||||
|
(CVE-2015-5154)
|
||||||
|
|
||||||
|
If the end_transfer_func of a command is called because enough data has
|
||||||
|
been read or written for the current PIO transfer, and it fails to
|
||||||
|
correctly call the command completion functions, the DRQ bit in the
|
||||||
|
status register and s->end_transfer_func may remain set. This allows the
|
||||||
|
guest to access further bytes in s->io_buffer beyond s->data_end, and
|
||||||
|
eventually overflowing the io_buffer.
|
||||||
|
|
||||||
|
One case where this currently happens is emulation of the ATAPI command
|
||||||
|
START STOP UNIT.
|
||||||
|
|
||||||
|
This patch fixes the problem by adding explicit array bounds checks
|
||||||
|
before accessing the buffer instead of relying on end_transfer_func to
|
||||||
|
function correctly.
|
||||||
|
|
||||||
|
Cc: qemu-stable@nongnu.org
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/core.c | 16 ++++++++++++++++
|
||||||
|
1 file changed, 16 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.2.5-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
+++ xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
@@ -3002,6 +3002,10 @@ static void ide_data_writew(void *opaque
|
||||||
|
buffered_pio_write(s, addr, 2);
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 2 > s->data_end) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
*(uint16_t *)p = le16_to_cpu(val);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -3021,6 +3025,10 @@ static uint32_t ide_data_readw(void *opa
|
||||||
|
buffered_pio_read(s, addr, 2);
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 2 > s->data_end) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = cpu_to_le16(*(uint16_t *)p);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -3040,6 +3048,10 @@ static void ide_data_writel(void *opaque
|
||||||
|
buffered_pio_write(s, addr, 4);
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 4 > s->data_end) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
*(uint32_t *)p = le32_to_cpu(val);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -3059,6 +3071,10 @@ static uint32_t ide_data_readl(void *opa
|
||||||
|
buffered_pio_read(s, addr, 4);
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 4 > s->data_end) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = cpu_to_le32(*(uint32_t *)p);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
@ -0,0 +1,68 @@
|
|||||||
|
From 1d3c2268f8708126a34064c2e0c1000b40e6f3e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:41:27 +0200
|
||||||
|
Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses
|
||||||
|
|
||||||
|
This is additional hardening against an end_transfer_func that fails to
|
||||||
|
clear the DRQ status bit. The bit must be unset as soon as the PIO
|
||||||
|
transfer has completed, so it's better to do this in a central place
|
||||||
|
instead of duplicating the code in all commands (and forgetting it in
|
||||||
|
some).
|
||||||
|
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/core.c | 16 ++++++++++++----
|
||||||
|
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.2.5-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
+++ xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
@@ -3016,8 +3016,10 @@ static void ide_data_writew(void *opaque
|
||||||
|
*(uint16_t *)p = le16_to_cpu(val);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
||||||
|
@@ -3039,8 +3041,10 @@ static uint32_t ide_data_readw(void *opa
|
||||||
|
ret = cpu_to_le16(*(uint16_t *)p);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3062,8 +3066,10 @@ static void ide_data_writel(void *opaque
|
||||||
|
*(uint32_t *)p = le32_to_cpu(val);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
||||||
|
@@ -3085,8 +3091,10 @@ static uint32_t ide_data_readl(void *opa
|
||||||
|
ret = cpu_to_le32(*(uint32_t *)p);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
Subject: ATAPI: STARTSTOPUNIT only eject/load media if powercondition is 0
|
||||||
|
From: Ronnie Sahlberg ronniesahlberg@gmail.com Tue Jul 31 11:28:26 2012 +1000
|
||||||
|
Date: Wed Sep 12 15:50:09 2012 +0200:
|
||||||
|
Git: ce560dcf20c14194db5ef3b9fc1ea592d4e68109
|
||||||
|
|
||||||
|
The START STOP UNIT command will only eject/load media if
|
||||||
|
power condition is zero.
|
||||||
|
|
||||||
|
If power condition is !0 then LOEJ and START will be ignored.
|
||||||
|
|
||||||
|
From MMC (sbc contains similar wordings too)
|
||||||
|
The Power Conditions field requests the block device to be placed
|
||||||
|
in the power condition defined in
|
||||||
|
Table 558. If this field has a value other than 0h then the Start
|
||||||
|
and LoEj bits shall be ignored.
|
||||||
|
|
||||||
|
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
|
||||||
|
From aa851d30acfbb9580098ac1dc82885530cb8b3c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:17:46 +0200
|
||||||
|
Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion
|
||||||
|
|
||||||
|
The command must be completed on all code paths. START STOP UNIT with
|
||||||
|
pwrcnd set should succeed without doing anything.
|
||||||
|
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/atapi.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
Index: xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.2.5-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
+++ xen-4.2.5-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
|
@@ -2095,9 +2095,16 @@ static void ide_atapi_cmd(IDEState *s)
|
||||||
|
break;
|
||||||
|
case GPCMD_START_STOP_UNIT:
|
||||||
|
{
|
||||||
|
- int start, eject;
|
||||||
|
+ int start, eject, pwrcnd;
|
||||||
|
start = packet[4] & 1;
|
||||||
|
eject = (packet[4] >> 1) & 1;
|
||||||
|
+ pwrcnd = buf[4] & 0xf0;
|
||||||
|
+
|
||||||
|
+ if (pwrcnd) {
|
||||||
|
+ /* eject/load only happens for power condition == 0 */
|
||||||
|
+ ide_atapi_cmd_ok(s);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (eject && !start) {
|
||||||
|
/* eject the disk */
|
@ -0,0 +1,74 @@
|
|||||||
|
From a9de14175548c04e0f8be7fae219246509ba46a9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:13:31 +0200
|
||||||
|
Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
|
||||||
|
(CVE-2015-5154)
|
||||||
|
|
||||||
|
If the end_transfer_func of a command is called because enough data has
|
||||||
|
been read or written for the current PIO transfer, and it fails to
|
||||||
|
correctly call the command completion functions, the DRQ bit in the
|
||||||
|
status register and s->end_transfer_func may remain set. This allows the
|
||||||
|
guest to access further bytes in s->io_buffer beyond s->data_end, and
|
||||||
|
eventually overflowing the io_buffer.
|
||||||
|
|
||||||
|
One case where this currently happens is emulation of the ATAPI command
|
||||||
|
START STOP UNIT.
|
||||||
|
|
||||||
|
This patch fixes the problem by adding explicit array bounds checks
|
||||||
|
before accessing the buffer instead of relying on end_transfer_func to
|
||||||
|
function correctly.
|
||||||
|
|
||||||
|
Cc: qemu-stable@nongnu.org
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/core.c | 16 ++++++++++++++++
|
||||||
|
1 file changed, 16 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
@@ -1901,6 +1901,10 @@ void ide_data_writew(void *opaque, uint3
|
||||||
|
}
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 2 > s->data_end) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
*(uint16_t *)p = le16_to_cpu(val);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -1922,6 +1926,10 @@ uint32_t ide_data_readw(void *opaque, ui
|
||||||
|
}
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 2 > s->data_end) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = cpu_to_le16(*(uint16_t *)p);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -1943,6 +1951,10 @@ void ide_data_writel(void *opaque, uint3
|
||||||
|
}
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 4 > s->data_end) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
*(uint32_t *)p = le32_to_cpu(val);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
@@ -1964,6 +1976,10 @@ uint32_t ide_data_readl(void *opaque, ui
|
||||||
|
}
|
||||||
|
|
||||||
|
p = s->data_ptr;
|
||||||
|
+ if (p + 4 > s->data_end) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = cpu_to_le32(*(uint32_t *)p);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
@ -0,0 +1,68 @@
|
|||||||
|
From 1d3c2268f8708126a34064c2e0c1000b40e6f3e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:41:27 +0200
|
||||||
|
Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses
|
||||||
|
|
||||||
|
This is additional hardening against an end_transfer_func that fails to
|
||||||
|
clear the DRQ status bit. The bit must be unset as soon as the PIO
|
||||||
|
transfer has completed, so it's better to do this in a central place
|
||||||
|
instead of duplicating the code in all commands (and forgetting it in
|
||||||
|
some).
|
||||||
|
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/core.c | 16 ++++++++++++----
|
||||||
|
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/core.c
|
||||||
|
@@ -1908,8 +1908,10 @@ void ide_data_writew(void *opaque, uint3
|
||||||
|
*(uint16_t *)p = le16_to_cpu(val);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
||||||
|
@@ -1933,8 +1935,10 @@ uint32_t ide_data_readw(void *opaque, ui
|
||||||
|
ret = cpu_to_le16(*(uint16_t *)p);
|
||||||
|
p += 2;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1958,8 +1962,10 @@ void ide_data_writel(void *opaque, uint3
|
||||||
|
*(uint32_t *)p = le32_to_cpu(val);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
||||||
|
@@ -1983,8 +1989,10 @@ uint32_t ide_data_readl(void *opaque, ui
|
||||||
|
ret = cpu_to_le32(*(uint32_t *)p);
|
||||||
|
p += 4;
|
||||||
|
s->data_ptr = p;
|
||||||
|
- if (p >= s->data_end)
|
||||||
|
+ if (p >= s->data_end) {
|
||||||
|
+ s->status &= ~DRQ_STAT;
|
||||||
|
s->end_transfer_func(s);
|
||||||
|
+ }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
From aa851d30acfbb9580098ac1dc82885530cb8b3c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Date: Wed, 3 Jun 2015 14:17:46 +0200
|
||||||
|
Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion
|
||||||
|
|
||||||
|
The command must be completed on all code paths. START STOP UNIT with
|
||||||
|
pwrcnd set should succeed without doing anything.
|
||||||
|
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
---
|
||||||
|
hw/ide/atapi.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/atapi.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/ide/atapi.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/atapi.c
|
||||||
|
@@ -879,6 +879,7 @@ static void cmd_start_stop_unit(IDEState
|
||||||
|
|
||||||
|
if (pwrcnd) {
|
||||||
|
/* eject/load only happens for power condition == 0 */
|
||||||
|
+ ide_atapi_cmd_ok(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- xen-4.2.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
+++ xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
||||||
@@ -935,8 +935,9 @@ static inline void ide_dma_submit_check(
|
@@ -935,8 +935,9 @@ static inline void ide_dma_submit_check(
|
||||||
|
|
||||||
static inline void ide_set_irq(IDEState *s)
|
static inline void ide_set_irq(IDEState *s)
|
||||||
@ -74,7 +74,7 @@ Index: xen-4.2.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
|
|||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ide_atapi_io_error(s, ret);
|
ide_atapi_io_error(s, ret);
|
||||||
@@ -2365,7 +2368,7 @@ static void cdrom_change_cb(void *opaque
|
@@ -2372,7 +2375,7 @@ static void cdrom_change_cb(void *opaque
|
||||||
IDEState *s = opaque;
|
IDEState *s = opaque;
|
||||||
uint64_t nb_sectors;
|
uint64_t nb_sectors;
|
||||||
|
|
||||||
|
53
xen.changes
53
xen.changes
@ -1,3 +1,51 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 28 09:04:13 MDT 2015 - carnold@suse.com
|
||||||
|
|
||||||
|
- bsc#939712 - VUL-0: XSA-140: QEMU leak of uninitialized heap
|
||||||
|
memory in rtl8139 device model
|
||||||
|
xsa140-qemuu-1.patch
|
||||||
|
xsa140-qemuu-2.patch
|
||||||
|
xsa140-qemuu-3.patch
|
||||||
|
xsa140-qemuu-4.patch
|
||||||
|
xsa140-qemuu-5.patch
|
||||||
|
xsa140-qemuu-6.patch
|
||||||
|
xsa140-qemuu-7.patch
|
||||||
|
xsa140-qemut-1.patch
|
||||||
|
xsa140-qemut-2.patch
|
||||||
|
xsa140-qemut-3.patch
|
||||||
|
xsa140-qemut-4.patch
|
||||||
|
xsa140-qemut-5.patch
|
||||||
|
xsa140-qemut-6.patch
|
||||||
|
xsa140-qemut-7.patch
|
||||||
|
- bsc#939709 - VUL-0: XSA-139: xen: Use after free in QEMU/Xen
|
||||||
|
block unplug protocol
|
||||||
|
xsa139-qemuu.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 21 10:03:24 UTC 2015 - ohering@suse.de
|
||||||
|
|
||||||
|
- bsc#937371 - xen vm's running after reboot
|
||||||
|
xendomains-libvirtd-conflict.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Jul 16 10:14:12 MDT 2015 - carnold@suse.com
|
||||||
|
|
||||||
|
- bsc#938344 - VUL-0: CVE-2015-5154: qemu,kvm,xen: host code
|
||||||
|
execution via IDE subsystem CD-ROM
|
||||||
|
CVE-2015-5154-qemuu-check-array-bounds-before-writing-to-io_buffer.patch
|
||||||
|
CVE-2015-5154-qemut-check-array-bounds-before-writing-to-io_buffer.patch
|
||||||
|
CVE-2015-5154-qemuu-fix-START-STOP-UNIT-command-completion.patch
|
||||||
|
CVE-2015-5154-qemut-fix-START-STOP-UNIT-command-completion.patch
|
||||||
|
CVE-2015-5154-qemuu-clear-DRQ-after-handling-all-expected-accesses.patch
|
||||||
|
CVE-2015-5154-qemut-clear-DRQ-after-handling-all-expected-accesses.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jul 15 08:28:23 UTC 2015 - ohering@suse.de
|
||||||
|
|
||||||
|
- Remove xendomains.service from systemd preset file because it
|
||||||
|
conflicts with libvirt-guests.service (bnc#937371)
|
||||||
|
Its up to the admin to run systemctl enable xendomains.service
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Jul 8 11:38:26 MDT 2015 - carnold@suse.com
|
Wed Jul 8 11:38:26 MDT 2015 - carnold@suse.com
|
||||||
|
|
||||||
@ -48,6 +96,11 @@ Wed Jul 8 11:38:26 MDT 2015 - carnold@suse.com
|
|||||||
qemu-MSI-X-latch-writes.patch
|
qemu-MSI-X-latch-writes.patch
|
||||||
x86-MSI-X-guest-mask.patch
|
x86-MSI-X-guest-mask.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 7 13:35:34 UTC 2015 - ohering@suse.de
|
||||||
|
|
||||||
|
- Adjust more places to use br0 instead of xenbr0
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Jun 30 08:25:35 MDT 2015 - carnold@suse.com
|
Tue Jun 30 08:25:35 MDT 2015 - carnold@suse.com
|
||||||
|
|
||||||
|
46
xen.spec
46
xen.spec
@ -15,7 +15,6 @@
|
|||||||
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
# needssslcertforbuild
|
# needssslcertforbuild
|
||||||
|
|
||||||
Name: xen
|
Name: xen
|
||||||
@ -216,6 +215,21 @@ Patch11: 559b9dd6-x86-p2m-ept-don-t-unmap-in-use-EPT-pagetable.patch
|
|||||||
Patch12: 559bdde5-pull-in-latest-linux-earlycpio.patch
|
Patch12: 559bdde5-pull-in-latest-linux-earlycpio.patch
|
||||||
Patch131: CVE-2015-4106-xsa131-9.patch
|
Patch131: CVE-2015-4106-xsa131-9.patch
|
||||||
Patch137: CVE-2015-3259-xsa137.patch
|
Patch137: CVE-2015-3259-xsa137.patch
|
||||||
|
Patch139: xsa139-qemuu.patch
|
||||||
|
Patch14001: xsa140-qemuu-1.patch
|
||||||
|
Patch14002: xsa140-qemuu-2.patch
|
||||||
|
Patch14003: xsa140-qemuu-3.patch
|
||||||
|
Patch14004: xsa140-qemuu-4.patch
|
||||||
|
Patch14005: xsa140-qemuu-5.patch
|
||||||
|
Patch14006: xsa140-qemuu-6.patch
|
||||||
|
Patch14007: xsa140-qemuu-7.patch
|
||||||
|
Patch14011: xsa140-qemut-1.patch
|
||||||
|
Patch14012: xsa140-qemut-2.patch
|
||||||
|
Patch14013: xsa140-qemut-3.patch
|
||||||
|
Patch14014: xsa140-qemut-4.patch
|
||||||
|
Patch14015: xsa140-qemut-5.patch
|
||||||
|
Patch14016: xsa140-qemut-6.patch
|
||||||
|
Patch14017: xsa140-qemut-7.patch
|
||||||
# Upstream qemu
|
# Upstream qemu
|
||||||
Patch250: VNC-Support-for-ExtendedKeyEvent-client-message.patch
|
Patch250: VNC-Support-for-ExtendedKeyEvent-client-message.patch
|
||||||
Patch251: 0001-net-move-the-tap-buffer-into-TAPState.patch
|
Patch251: 0001-net-move-the-tap-buffer-into-TAPState.patch
|
||||||
@ -226,6 +240,12 @@ Patch255: 0005-e1000-multi-buffer-packet-support.patch
|
|||||||
Patch256: 0006-e1000-clear-EOP-for-multi-buffer-descriptors.patch
|
Patch256: 0006-e1000-clear-EOP-for-multi-buffer-descriptors.patch
|
||||||
Patch257: 0007-e1000-verify-we-have-buffers-upfront.patch
|
Patch257: 0007-e1000-verify-we-have-buffers-upfront.patch
|
||||||
Patch258: 0008-e1000-check-buffer-availability.patch
|
Patch258: 0008-e1000-check-buffer-availability.patch
|
||||||
|
Patch259: CVE-2015-5154-qemuu-check-array-bounds-before-writing-to-io_buffer.patch
|
||||||
|
Patch260: CVE-2015-5154-qemuu-fix-START-STOP-UNIT-command-completion.patch
|
||||||
|
Patch261: CVE-2015-5154-qemuu-clear-DRQ-after-handling-all-expected-accesses.patch
|
||||||
|
Patch262: CVE-2015-5154-qemut-check-array-bounds-before-writing-to-io_buffer.patch
|
||||||
|
Patch263: CVE-2015-5154-qemut-fix-START-STOP-UNIT-command-completion.patch
|
||||||
|
Patch264: CVE-2015-5154-qemut-clear-DRQ-after-handling-all-expected-accesses.patch
|
||||||
# Our platform specific patches
|
# Our platform specific patches
|
||||||
Patch301: xen-destdir.patch
|
Patch301: xen-destdir.patch
|
||||||
Patch302: vif-bridge-no-iptables.patch
|
Patch302: vif-bridge-no-iptables.patch
|
||||||
@ -294,6 +314,7 @@ Patch467: libxl.add-option-to-disable-disk-cache-flushes-in-qdisk.patch
|
|||||||
Patch470: qemu-xen-upstream-qdisk-cache-unsafe.patch
|
Patch470: qemu-xen-upstream-qdisk-cache-unsafe.patch
|
||||||
Patch471: qemu-xen-enable-spice-support.patch
|
Patch471: qemu-xen-enable-spice-support.patch
|
||||||
Patch472: tigervnc-long-press.patch
|
Patch472: tigervnc-long-press.patch
|
||||||
|
Patch473: xendomains-libvirtd-conflict.patch
|
||||||
# Hypervisor and PV driver Patches
|
# Hypervisor and PV driver Patches
|
||||||
Patch501: x86-ioapic-ack-default.patch
|
Patch501: x86-ioapic-ack-default.patch
|
||||||
Patch502: x86-cpufreq-report.patch
|
Patch502: x86-cpufreq-report.patch
|
||||||
@ -562,6 +583,21 @@ Authors:
|
|||||||
%patch12 -p1
|
%patch12 -p1
|
||||||
%patch131 -p1
|
%patch131 -p1
|
||||||
%patch137 -p1
|
%patch137 -p1
|
||||||
|
%patch139 -p1
|
||||||
|
%patch14001 -p1
|
||||||
|
%patch14002 -p1
|
||||||
|
%patch14003 -p1
|
||||||
|
%patch14004 -p1
|
||||||
|
%patch14005 -p1
|
||||||
|
%patch14006 -p1
|
||||||
|
%patch14007 -p1
|
||||||
|
%patch14011 -p1
|
||||||
|
%patch14012 -p1
|
||||||
|
%patch14013 -p1
|
||||||
|
%patch14014 -p1
|
||||||
|
%patch14015 -p1
|
||||||
|
%patch14016 -p1
|
||||||
|
%patch14017 -p1
|
||||||
# Upstream qemu patches
|
# Upstream qemu patches
|
||||||
%patch250 -p1
|
%patch250 -p1
|
||||||
%patch251 -p1
|
%patch251 -p1
|
||||||
@ -572,6 +608,12 @@ Authors:
|
|||||||
%patch256 -p1
|
%patch256 -p1
|
||||||
%patch257 -p1
|
%patch257 -p1
|
||||||
%patch258 -p1
|
%patch258 -p1
|
||||||
|
%patch259 -p1
|
||||||
|
%patch260 -p1
|
||||||
|
%patch261 -p1
|
||||||
|
%patch262 -p1
|
||||||
|
%patch263 -p1
|
||||||
|
%patch264 -p1
|
||||||
# Our platform specific patches
|
# Our platform specific patches
|
||||||
%patch301 -p1
|
%patch301 -p1
|
||||||
%patch302 -p1
|
%patch302 -p1
|
||||||
@ -639,6 +681,7 @@ Authors:
|
|||||||
%patch470 -p1
|
%patch470 -p1
|
||||||
%patch471 -p1
|
%patch471 -p1
|
||||||
%patch472 -p1
|
%patch472 -p1
|
||||||
|
%patch473 -p1
|
||||||
# Hypervisor and PV driver Patches
|
# Hypervisor and PV driver Patches
|
||||||
%patch501 -p1
|
%patch501 -p1
|
||||||
%patch502 -p1
|
%patch502 -p1
|
||||||
@ -956,7 +999,6 @@ mv $RPM_BUILD_ROOT/etc/udev/rules.d/xen-backend.rules $RPM_BUILD_ROOT/etc/udev/r
|
|||||||
mkdir -vp $RPM_BUILD_ROOT%_presetdir
|
mkdir -vp $RPM_BUILD_ROOT%_presetdir
|
||||||
cat > $RPM_BUILD_ROOT%_presetdir/00-%{name}.preset <<EOF
|
cat > $RPM_BUILD_ROOT%_presetdir/00-%{name}.preset <<EOF
|
||||||
enable xencommons.service
|
enable xencommons.service
|
||||||
enable xendomains.service
|
|
||||||
EOF
|
EOF
|
||||||
%endif
|
%endif
|
||||||
cp -bavL %{S:41} $RPM_BUILD_ROOT%{_unitdir}
|
cp -bavL %{S:41} $RPM_BUILD_ROOT%{_unitdir}
|
||||||
|
20
xendomains-libvirtd-conflict.patch
Normal file
20
xendomains-libvirtd-conflict.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
xendomains conflicts with libvirtd (bnc#937371)
|
||||||
|
|
||||||
|
It saves domains without telling libvirt
|
||||||
|
It restores domains without telling libvirt
|
||||||
|
---
|
||||||
|
tools/hotplug/Linux/systemd/xendomains.service.in | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||||
|
+++ xen-4.5.1-testing/tools/hotplug/Linux/systemd/xendomains.service.in
|
||||||
|
@@ -5,6 +5,7 @@ After=proc-xen.mount xenstored.service x
|
||||||
|
After=network-online.target
|
||||||
|
After=remote-fs.target
|
||||||
|
ConditionPathExists=/proc/xen/capabilities
|
||||||
|
+Conflicts=libvirtd.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
37
xsa139-qemuu.patch
Normal file
37
xsa139-qemuu.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
References: bsc#939709 XSA-139
|
||||||
|
|
||||||
|
pci_piix3_xen_ide_unplug should completely unhook the unplugged
|
||||||
|
IDEDevice from the corresponding BlockBackend, otherwise the next call
|
||||||
|
to release_drive will try to detach the drive again.
|
||||||
|
|
||||||
|
Suggested-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
||||||
|
---
|
||||||
|
hw/ide/piix.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/piix.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/ide/piix.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/ide/piix.c
|
||||||
|
@@ -172,6 +172,7 @@ int pci_piix3_xen_ide_unplug(DeviceState
|
||||||
|
PCIIDEState *pci_ide;
|
||||||
|
DriveInfo *di;
|
||||||
|
int i = 0;
|
||||||
|
+ IDEDevice *idedev;
|
||||||
|
|
||||||
|
pci_ide = PCI_IDE(dev);
|
||||||
|
|
||||||
|
@@ -184,6 +185,12 @@ int pci_piix3_xen_ide_unplug(DeviceState
|
||||||
|
}
|
||||||
|
bdrv_close(di->bdrv);
|
||||||
|
pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
|
||||||
|
+ if (!(i % 2)) {
|
||||||
|
+ idedev = pci_ide->bus[di->bus].master;
|
||||||
|
+ } else {
|
||||||
|
+ idedev = pci_ide->bus[di->bus].slave;
|
||||||
|
+ }
|
||||||
|
+ idedev->conf.bs = NULL;
|
||||||
|
drive_put_ref(di);
|
||||||
|
}
|
||||||
|
}
|
78
xsa140-qemut-1.patch
Normal file
78
xsa140-qemut-1.patch
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 5e0c290415b9d57077a86e70c8e6a058868334d3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:16:58 +0100
|
||||||
|
Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing
|
||||||
|
|
||||||
|
Transmit offload needs to parse packet headers. If header fields have
|
||||||
|
unexpected values the offload processing is skipped.
|
||||||
|
|
||||||
|
The code currently uses nested ifs because there is relatively little
|
||||||
|
input validation. The next patches will add missing input validation
|
||||||
|
and a goto label is more appropriate to avoid deep if statement nesting.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 41 ++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 22 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2113,26 +2113,30 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
size_t eth_payload_len = 0;
|
||||||
|
|
||||||
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
|
- if (proto == ETH_P_IP)
|
||||||
|
+ if (proto != ETH_P_IP)
|
||||||
|
{
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* not aligned */
|
||||||
|
- eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
- eth_payload_len = saved_size - ETH_HLEN;
|
||||||
|
-
|
||||||
|
- ip = (ip_header*)eth_payload_data;
|
||||||
|
-
|
||||||
|
- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4));
|
||||||
|
- ip = NULL;
|
||||||
|
- } else {
|
||||||
|
- hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
- ip_protocol = ip->ip_p;
|
||||||
|
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
- }
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
|
||||||
|
+
|
||||||
|
+ /* not aligned */
|
||||||
|
+ eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
+ eth_payload_len = saved_size - ETH_HLEN;
|
||||||
|
+
|
||||||
|
+ ip = (ip_header*)eth_payload_data;
|
||||||
|
+
|
||||||
|
+ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d "
|
||||||
|
+ "expected %d\n", IP_HEADER_VERSION(ip),
|
||||||
|
+ IP_HEADER_VERSION_4));
|
||||||
|
+ goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
+ ip_protocol = ip->ip_p;
|
||||||
|
+ ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
+
|
||||||
|
if (ip)
|
||||||
|
{
|
||||||
|
if (txdw0 & CP_TX_IPCS)
|
||||||
|
@@ -2315,6 +2319,7 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+skip_offload:
|
||||||
|
/* update tally counter */
|
||||||
|
++s->tally_counters.TxOk;
|
||||||
|
|
339
xsa140-qemut-2.patch
Normal file
339
xsa140-qemut-2.patch
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 2d7d80e8dc160904fa7276cc05da26c062a50066 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:16:59 +0100
|
||||||
|
Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement
|
||||||
|
|
||||||
|
The previous patch stopped using the ip pointer as an indicator that the
|
||||||
|
IP header is present. When we reach the if (ip) {...} statement we know
|
||||||
|
ip is always non-NULL.
|
||||||
|
|
||||||
|
Remove the if statement to reduce nesting.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 305 +++++++++++++++++++++++++++----------------------------
|
||||||
|
1 file changed, 151 insertions(+), 154 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2137,187 +2137,184 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
|
||||||
|
- if (ip)
|
||||||
|
+ if (txdw0 & CP_TX_IPCS)
|
||||||
|
{
|
||||||
|
- if (txdw0 & CP_TX_IPCS)
|
||||||
|
- {
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
|
||||||
|
|
||||||
|
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
- /* bad packet header len */
|
||||||
|
- /* or packet too short */
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
- }
|
||||||
|
+ if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
+ /* bad packet header len */
|
||||||
|
+ /* or packet too short */
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ else
|
||||||
|
{
|
||||||
|
-#if defined (DEBUG_RTL8139)
|
||||||
|
- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
-#endif
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
|
||||||
|
- ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss));
|
||||||
|
-
|
||||||
|
- int tcp_send_offset = 0;
|
||||||
|
- int send_count = 0;
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* maximum IP header length is 60 bytes */
|
||||||
|
- uint8_t saved_ip_header[60];
|
||||||
|
+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ {
|
||||||
|
+ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
|
- /* save IP header template; data area is used in tcp checksum calculation */
|
||||||
|
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
|
||||||
|
+ ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss));
|
||||||
|
|
||||||
|
- /* a placeholder for checksum calculation routine in tcp case */
|
||||||
|
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
+ int tcp_send_offset = 0;
|
||||||
|
+ int send_count = 0;
|
||||||
|
|
||||||
|
- /* pointer to TCP header */
|
||||||
|
- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
+ /* maximum IP header length is 60 bytes */
|
||||||
|
+ uint8_t saved_ip_header[60];
|
||||||
|
|
||||||
|
- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
+ /* save IP header template; data area is used in tcp checksum calculation */
|
||||||
|
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
|
||||||
|
- /* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
- int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
|
+ /* a placeholder for checksum calculation routine in tcp case */
|
||||||
|
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n",
|
||||||
|
- ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size));
|
||||||
|
+ /* pointer to TCP header */
|
||||||
|
+ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
|
||||||
|
- /* note the cycle below overwrites IP header data,
|
||||||
|
- but restores it from saved_ip_header before sending packet */
|
||||||
|
+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
- int is_last_frame = 0;
|
||||||
|
+ /* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
+ int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
+ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
|
|
||||||
|
- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
||||||
|
- {
|
||||||
|
- uint16_t chunk_size = tcp_chunk_size;
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n",
|
||||||
|
+ ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size));
|
||||||
|
|
||||||
|
- /* check if this is the last frame */
|
||||||
|
- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
||||||
|
- {
|
||||||
|
- is_last_frame = 1;
|
||||||
|
- chunk_size = tcp_data_len - tcp_send_offset;
|
||||||
|
- }
|
||||||
|
+ /* note the cycle below overwrites IP header data,
|
||||||
|
+ but restores it from saved_ip_header before sending packet */
|
||||||
|
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
|
||||||
|
+ int is_last_frame = 0;
|
||||||
|
|
||||||
|
- /* add 4 TCP pseudoheader fields */
|
||||||
|
- /* copy IP source and destination fields */
|
||||||
|
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
+ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
||||||
|
+ {
|
||||||
|
+ uint16_t chunk_size = tcp_chunk_size;
|
||||||
|
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
|
||||||
|
+ /* check if this is the last frame */
|
||||||
|
+ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
||||||
|
+ {
|
||||||
|
+ is_last_frame = 1;
|
||||||
|
+ chunk_size = tcp_data_len - tcp_send_offset;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (tcp_send_offset)
|
||||||
|
- {
|
||||||
|
- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
||||||
|
- }
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
|
||||||
|
|
||||||
|
- /* keep PUSH and FIN flags only for the last frame */
|
||||||
|
- if (!is_last_frame)
|
||||||
|
- {
|
||||||
|
- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
||||||
|
- }
|
||||||
|
+ /* add 4 TCP pseudoheader fields */
|
||||||
|
+ /* copy IP source and destination fields */
|
||||||
|
+ memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
|
||||||
|
- /* recalculate TCP checksum */
|
||||||
|
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_tcpip_hdr->zeros = 0;
|
||||||
|
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = 0;
|
||||||
|
+ if (tcp_send_offset)
|
||||||
|
+ {
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
|
||||||
|
+ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum));
|
||||||
|
+ /* keep PUSH and FIN flags only for the last frame */
|
||||||
|
+ if (!is_last_frame)
|
||||||
|
+ {
|
||||||
|
+ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
+ /* recalculate TCP checksum */
|
||||||
|
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_tcpip_hdr->zeros = 0;
|
||||||
|
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
+ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
||||||
|
|
||||||
|
- /* restore IP header */
|
||||||
|
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
+ p_tcp_hdr->th_sum = 0;
|
||||||
|
|
||||||
|
- /* set IP data length and recalculate IP checksum */
|
||||||
|
- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
||||||
|
+ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum));
|
||||||
|
|
||||||
|
- /* increment IP id for subsequent frames */
|
||||||
|
- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
||||||
|
+ p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
+ /* restore IP header */
|
||||||
|
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
|
||||||
|
- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
|
||||||
|
- rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
|
||||||
|
+ /* set IP data length and recalculate IP checksum */
|
||||||
|
+ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
||||||
|
|
||||||
|
- /* add transferred count to TCP sequence number */
|
||||||
|
- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
- ++send_count;
|
||||||
|
- }
|
||||||
|
+ /* increment IP id for subsequent frames */
|
||||||
|
+ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
||||||
|
|
||||||
|
- /* Stop sending this frame */
|
||||||
|
- saved_size = 0;
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
+
|
||||||
|
+ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
|
||||||
|
+ rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
|
||||||
|
+
|
||||||
|
+ /* add transferred count to TCP sequence number */
|
||||||
|
+ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
+ ++send_count;
|
||||||
|
}
|
||||||
|
- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
||||||
|
- {
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n"));
|
||||||
|
|
||||||
|
- /* maximum IP header length is 60 bytes */
|
||||||
|
- uint8_t saved_ip_header[60];
|
||||||
|
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
+ /* Stop sending this frame */
|
||||||
|
+ saved_size = 0;
|
||||||
|
+ }
|
||||||
|
+ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
||||||
|
+ {
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n"));
|
||||||
|
|
||||||
|
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
+ /* maximum IP header length is 60 bytes */
|
||||||
|
+ uint8_t saved_ip_header[60];
|
||||||
|
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
|
||||||
|
- /* add 4 TCP pseudoheader fields */
|
||||||
|
- /* copy IP source and destination fields */
|
||||||
|
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
|
||||||
|
- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
- {
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
|
||||||
|
+ /* add 4 TCP pseudoheader fields */
|
||||||
|
+ /* copy IP source and destination fields */
|
||||||
|
+ memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
|
||||||
|
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_tcpip_hdr->zeros = 0;
|
||||||
|
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ {
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
|
||||||
|
|
||||||
|
- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
||||||
|
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_tcpip_hdr->zeros = 0;
|
||||||
|
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
+ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = 0;
|
||||||
|
+ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
||||||
|
|
||||||
|
- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum));
|
||||||
|
+ p_tcp_hdr->th_sum = 0;
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
- }
|
||||||
|
- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
||||||
|
- {
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len));
|
||||||
|
+ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum));
|
||||||
|
|
||||||
|
- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_udpip_hdr->zeros = 0;
|
||||||
|
- p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
||||||
|
- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+ p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
+ }
|
||||||
|
+ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
||||||
|
+ {
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len));
|
||||||
|
|
||||||
|
- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
||||||
|
+ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_udpip_hdr->zeros = 0;
|
||||||
|
+ p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
||||||
|
+ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
|
||||||
|
- p_udp_hdr->uh_sum = 0;
|
||||||
|
+ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
||||||
|
|
||||||
|
- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum));
|
||||||
|
+ p_udp_hdr->uh_sum = 0;
|
||||||
|
|
||||||
|
- p_udp_hdr->uh_sum = udp_checksum;
|
||||||
|
- }
|
||||||
|
+ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum));
|
||||||
|
|
||||||
|
- /* restore IP header */
|
||||||
|
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
+ p_udp_hdr->uh_sum = udp_checksum;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* restore IP header */
|
||||||
|
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
skip_offload:
|
||||||
|
/* update tally counter */
|
38
xsa140-qemut-3.patch
Normal file
38
xsa140-qemut-3.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 043d28507ef7c5fdc34866f5e3b27a72bd0cd072 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:00 +0100
|
||||||
|
Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header
|
||||||
|
|
||||||
|
Transmit offload features access Ethernet and IP headers the packet. If
|
||||||
|
the packet is too short we must not attempt to access header fields:
|
||||||
|
|
||||||
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
|
...
|
||||||
|
eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
...
|
||||||
|
ip = (ip_header*)eth_payload_data;
|
||||||
|
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2103,6 +2103,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
#define ETH_HLEN 14
|
||||||
|
#define ETH_MTU 1500
|
||||||
|
|
||||||
|
+ /* Large enough for Ethernet and IP headers? */
|
||||||
|
+ if (saved_size < ETH_HLEN + sizeof(ip_header)) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* ip packet header */
|
||||||
|
ip_header *ip = 0;
|
||||||
|
int hlen = 0;
|
50
xsa140-qemut-4.patch
Normal file
50
xsa140-qemut-4.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 5a75d242fe019d05b46ef9bc330a6892525c84a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:01 +0100
|
||||||
|
Subject: [PATCH 4/7] rtl8139: check IP Header Length field
|
||||||
|
|
||||||
|
The IP Header Length field was only checked in the IP checksum case, but
|
||||||
|
is used in other cases too.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 19 ++++++++-----------
|
||||||
|
1 file changed, 8 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2139,6 +2139,10 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
|
||||||
|
hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
+ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
|
||||||
|
@@ -2146,16 +2150,9 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
{
|
||||||
|
DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
|
||||||
|
|
||||||
|
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
- /* bad packet header len */
|
||||||
|
- /* or packet too short */
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
- DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
- }
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
+ DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
33
xsa140-qemut-5.patch
Normal file
33
xsa140-qemut-5.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 6c79ea275d72bc1fd88bdcf1e7d231b2c9c865de Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:02 +0100
|
||||||
|
Subject: [PATCH 5/7] rtl8139: check IP Total Length field
|
||||||
|
|
||||||
|
The IP Total Length field includes the IP header and data. Make sure it
|
||||||
|
is valid and does not exceed the Ethernet payload size.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2144,7 +2144,12 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
+
|
||||||
|
+ ip_data_len = be16_to_cpu(ip->ip_len);
|
||||||
|
+ if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+ ip_data_len -= hlen;
|
||||||
|
|
||||||
|
if (txdw0 & CP_TX_IPCS)
|
||||||
|
{
|
34
xsa140-qemut-6.patch
Normal file
34
xsa140-qemut-6.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 30aa7be430e7c982e9163f3bcc745d3aa57b6aa4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:03 +0100
|
||||||
|
Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header
|
||||||
|
|
||||||
|
TCP Large Segment Offload accesses the TCP header in the packet. If the
|
||||||
|
packet is too short we must not attempt to access header fields:
|
||||||
|
|
||||||
|
tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2162,6 +2162,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
|
||||||
|
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
{
|
||||||
|
+ /* Large enough for the TCP header? */
|
||||||
|
+ if (ip_data_len < sizeof(tcp_header)) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
|
DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
|
31
xsa140-qemut-7.patch
Normal file
31
xsa140-qemut-7.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 9a084807bf6ca7c16d997a236d304111894a6539 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:04 +0100
|
||||||
|
Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field
|
||||||
|
|
||||||
|
The TCP Data Offset field contains the length of the header. Make sure
|
||||||
|
it is valid and does not exceed the IP data length.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-traditional-dir-remote/hw/rtl8139.c
|
||||||
|
@@ -2190,6 +2190,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
|
||||||
|
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
+ /* Invalid TCP data offset? */
|
||||||
|
+ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
80
xsa140-qemuu-1.patch
Normal file
80
xsa140-qemuu-1.patch
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 5e0c290415b9d57077a86e70c8e6a058868334d3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:16:58 +0100
|
||||||
|
Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing
|
||||||
|
|
||||||
|
Transmit offload needs to parse packet headers. If header fields have
|
||||||
|
unexpected values the offload processing is skipped.
|
||||||
|
|
||||||
|
The code currently uses nested ifs because there is relatively little
|
||||||
|
input validation. The next patches will add missing input validation
|
||||||
|
and a goto label is more appropriate to avoid deep if statement nesting.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 41 ++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 22 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2171,28 +2171,30 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
size_t eth_payload_len = 0;
|
||||||
|
|
||||||
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
|
- if (proto == ETH_P_IP)
|
||||||
|
+ if (proto != ETH_P_IP)
|
||||||
|
{
|
||||||
|
- DPRINTF("+++ C+ mode has IP packet\n");
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* not aligned */
|
||||||
|
- eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
- eth_payload_len = saved_size - ETH_HLEN;
|
||||||
|
-
|
||||||
|
- ip = (ip_header*)eth_payload_data;
|
||||||
|
-
|
||||||
|
- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
- DPRINTF("+++ C+ mode packet has bad IP version %d "
|
||||||
|
- "expected %d\n", IP_HEADER_VERSION(ip),
|
||||||
|
- IP_HEADER_VERSION_4);
|
||||||
|
- ip = NULL;
|
||||||
|
- } else {
|
||||||
|
- hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
- ip_protocol = ip->ip_p;
|
||||||
|
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
- }
|
||||||
|
+ DPRINTF("+++ C+ mode has IP packet\n");
|
||||||
|
+
|
||||||
|
+ /* not aligned */
|
||||||
|
+ eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
+ eth_payload_len = saved_size - ETH_HLEN;
|
||||||
|
+
|
||||||
|
+ ip = (ip_header*)eth_payload_data;
|
||||||
|
+
|
||||||
|
+ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
+ DPRINTF("+++ C+ mode packet has bad IP version %d "
|
||||||
|
+ "expected %d\n", IP_HEADER_VERSION(ip),
|
||||||
|
+ IP_HEADER_VERSION_4);
|
||||||
|
+ goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
+ ip_protocol = ip->ip_p;
|
||||||
|
+ ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
+
|
||||||
|
if (ip)
|
||||||
|
{
|
||||||
|
if (txdw0 & CP_TX_IPCS)
|
||||||
|
@@ -2388,6 +2390,7 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+skip_offload:
|
||||||
|
/* update tally counter */
|
||||||
|
++s->tally_counters.TxOk;
|
||||||
|
|
372
xsa140-qemuu-2.patch
Normal file
372
xsa140-qemuu-2.patch
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 2d7d80e8dc160904fa7276cc05da26c062a50066 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:16:59 +0100
|
||||||
|
Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement
|
||||||
|
|
||||||
|
The previous patch stopped using the ip pointer as an indicator that the
|
||||||
|
IP header is present. When we reach the if (ip) {...} statement we know
|
||||||
|
ip is always non-NULL.
|
||||||
|
|
||||||
|
Remove the if statement to reduce nesting.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 305 +++++++++++++++++++++++++++----------------------------
|
||||||
|
1 file changed, 151 insertions(+), 154 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2195,198 +2195,195 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
|
||||||
|
- if (ip)
|
||||||
|
+ if (txdw0 & CP_TX_IPCS)
|
||||||
|
{
|
||||||
|
- if (txdw0 & CP_TX_IPCS)
|
||||||
|
- {
|
||||||
|
- DPRINTF("+++ C+ mode need IP checksum\n");
|
||||||
|
+ DPRINTF("+++ C+ mode need IP checksum\n");
|
||||||
|
|
||||||
|
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
- /* bad packet header len */
|
||||||
|
- /* or packet too short */
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
|
- hlen, ip->ip_sum);
|
||||||
|
- }
|
||||||
|
+ if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
+ /* bad packet header len */
|
||||||
|
+ /* or packet too short */
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ else
|
||||||
|
{
|
||||||
|
- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
-
|
||||||
|
- DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
||||||
|
- "frame data %d specified MSS=%d\n", ETH_MTU,
|
||||||
|
- ip_data_len, saved_size - ETH_HLEN, large_send_mss);
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
|
+ hlen, ip->ip_sum);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- int tcp_send_offset = 0;
|
||||||
|
- int send_count = 0;
|
||||||
|
+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ {
|
||||||
|
+ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
|
- /* maximum IP header length is 60 bytes */
|
||||||
|
- uint8_t saved_ip_header[60];
|
||||||
|
+ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
||||||
|
+ "frame data %d specified MSS=%d\n", ETH_MTU,
|
||||||
|
+ ip_data_len, saved_size - ETH_HLEN, large_send_mss);
|
||||||
|
|
||||||
|
- /* save IP header template; data area is used in tcp checksum calculation */
|
||||||
|
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
+ int tcp_send_offset = 0;
|
||||||
|
+ int send_count = 0;
|
||||||
|
|
||||||
|
- /* a placeholder for checksum calculation routine in tcp case */
|
||||||
|
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
+ /* maximum IP header length is 60 bytes */
|
||||||
|
+ uint8_t saved_ip_header[60];
|
||||||
|
|
||||||
|
- /* pointer to TCP header */
|
||||||
|
- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
+ /* save IP header template; data area is used in tcp checksum calculation */
|
||||||
|
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
|
||||||
|
- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
+ /* a placeholder for checksum calculation routine in tcp case */
|
||||||
|
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
|
||||||
|
- /* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
- int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
|
+ /* pointer to TCP header */
|
||||||
|
+ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
|
||||||
|
- DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
|
||||||
|
- "data len %d TCP chunk size %d\n", ip_data_len,
|
||||||
|
- tcp_hlen, tcp_data_len, tcp_chunk_size);
|
||||||
|
+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
- /* note the cycle below overwrites IP header data,
|
||||||
|
- but restores it from saved_ip_header before sending packet */
|
||||||
|
+ /* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
+ int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
+ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
|
|
||||||
|
- int is_last_frame = 0;
|
||||||
|
+ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
|
||||||
|
+ "data len %d TCP chunk size %d\n", ip_data_len,
|
||||||
|
+ tcp_hlen, tcp_data_len, tcp_chunk_size);
|
||||||
|
|
||||||
|
- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
||||||
|
- {
|
||||||
|
- uint16_t chunk_size = tcp_chunk_size;
|
||||||
|
+ /* note the cycle below overwrites IP header data,
|
||||||
|
+ but restores it from saved_ip_header before sending packet */
|
||||||
|
|
||||||
|
- /* check if this is the last frame */
|
||||||
|
- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
||||||
|
- {
|
||||||
|
- is_last_frame = 1;
|
||||||
|
- chunk_size = tcp_data_len - tcp_send_offset;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
|
||||||
|
- be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
-
|
||||||
|
- /* add 4 TCP pseudoheader fields */
|
||||||
|
- /* copy IP source and destination fields */
|
||||||
|
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
-
|
||||||
|
- DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
|
||||||
|
- "packet with %d bytes data\n", tcp_hlen +
|
||||||
|
- chunk_size);
|
||||||
|
-
|
||||||
|
- if (tcp_send_offset)
|
||||||
|
- {
|
||||||
|
- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* keep PUSH and FIN flags only for the last frame */
|
||||||
|
- if (!is_last_frame)
|
||||||
|
- {
|
||||||
|
- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* recalculate TCP checksum */
|
||||||
|
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_tcpip_hdr->zeros = 0;
|
||||||
|
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
||||||
|
-
|
||||||
|
- p_tcp_hdr->th_sum = 0;
|
||||||
|
-
|
||||||
|
- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
||||||
|
- DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
|
||||||
|
- tcp_checksum);
|
||||||
|
-
|
||||||
|
- p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
-
|
||||||
|
- /* restore IP header */
|
||||||
|
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
-
|
||||||
|
- /* set IP data length and recalculate IP checksum */
|
||||||
|
- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
||||||
|
-
|
||||||
|
- /* increment IP id for subsequent frames */
|
||||||
|
- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
||||||
|
-
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
||||||
|
- DPRINTF("+++ C+ mode TSO IP header len=%d "
|
||||||
|
- "checksum=%04x\n", hlen, ip->ip_sum);
|
||||||
|
-
|
||||||
|
- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
||||||
|
- DPRINTF("+++ C+ mode TSO transferring packet size "
|
||||||
|
- "%d\n", tso_send_size);
|
||||||
|
- rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
|
||||||
|
- 0, (uint8_t *) dot1q_buffer);
|
||||||
|
-
|
||||||
|
- /* add transferred count to TCP sequence number */
|
||||||
|
- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
- ++send_count;
|
||||||
|
- }
|
||||||
|
+ int is_last_frame = 0;
|
||||||
|
|
||||||
|
- /* Stop sending this frame */
|
||||||
|
- saved_size = 0;
|
||||||
|
- }
|
||||||
|
- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
||||||
|
+ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
||||||
|
{
|
||||||
|
- DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
|
||||||
|
+ uint16_t chunk_size = tcp_chunk_size;
|
||||||
|
|
||||||
|
- /* maximum IP header length is 60 bytes */
|
||||||
|
- uint8_t saved_ip_header[60];
|
||||||
|
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
+ /* check if this is the last frame */
|
||||||
|
+ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
||||||
|
+ {
|
||||||
|
+ is_last_frame = 1;
|
||||||
|
+ chunk_size = tcp_data_len - tcp_send_offset;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
+ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
|
||||||
|
+ be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
|
||||||
|
/* add 4 TCP pseudoheader fields */
|
||||||
|
/* copy IP source and destination fields */
|
||||||
|
memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
|
||||||
|
- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
|
||||||
|
+ "packet with %d bytes data\n", tcp_hlen +
|
||||||
|
+ chunk_size);
|
||||||
|
+
|
||||||
|
+ if (tcp_send_offset)
|
||||||
|
{
|
||||||
|
- DPRINTF("+++ C+ mode calculating TCP checksum for "
|
||||||
|
- "packet with %d bytes data\n", ip_data_len);
|
||||||
|
+ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_tcpip_hdr->zeros = 0;
|
||||||
|
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+ /* keep PUSH and FIN flags only for the last frame */
|
||||||
|
+ if (!is_last_frame)
|
||||||
|
+ {
|
||||||
|
+ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
||||||
|
+ /* recalculate TCP checksum */
|
||||||
|
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_tcpip_hdr->zeros = 0;
|
||||||
|
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
+ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
||||||
|
+
|
||||||
|
+ p_tcp_hdr->th_sum = 0;
|
||||||
|
+
|
||||||
|
+ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
||||||
|
+ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
|
||||||
|
+ tcp_checksum);
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = 0;
|
||||||
|
+ p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
|
||||||
|
- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
- DPRINTF("+++ C+ mode TCP checksum %04x\n",
|
||||||
|
- tcp_checksum);
|
||||||
|
+ /* restore IP header */
|
||||||
|
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
|
||||||
|
- p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
- }
|
||||||
|
- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
||||||
|
- {
|
||||||
|
- DPRINTF("+++ C+ mode calculating UDP checksum for "
|
||||||
|
- "packet with %d bytes data\n", ip_data_len);
|
||||||
|
+ /* set IP data length and recalculate IP checksum */
|
||||||
|
+ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
||||||
|
|
||||||
|
- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
- p_udpip_hdr->zeros = 0;
|
||||||
|
- p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
||||||
|
- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+ /* increment IP id for subsequent frames */
|
||||||
|
+ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
||||||
|
|
||||||
|
- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
||||||
|
+ DPRINTF("+++ C+ mode TSO IP header len=%d "
|
||||||
|
+ "checksum=%04x\n", hlen, ip->ip_sum);
|
||||||
|
+
|
||||||
|
+ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
||||||
|
+ DPRINTF("+++ C+ mode TSO transferring packet size "
|
||||||
|
+ "%d\n", tso_send_size);
|
||||||
|
+ rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
|
||||||
|
+ 0, (uint8_t *) dot1q_buffer);
|
||||||
|
+
|
||||||
|
+ /* add transferred count to TCP sequence number */
|
||||||
|
+ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
||||||
|
+ ++send_count;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- p_udp_hdr->uh_sum = 0;
|
||||||
|
+ /* Stop sending this frame */
|
||||||
|
+ saved_size = 0;
|
||||||
|
+ }
|
||||||
|
+ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
||||||
|
+ {
|
||||||
|
+ DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
|
||||||
|
|
||||||
|
- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
- DPRINTF("+++ C+ mode UDP checksum %04x\n",
|
||||||
|
- udp_checksum);
|
||||||
|
+ /* maximum IP header length is 60 bytes */
|
||||||
|
+ uint8_t saved_ip_header[60];
|
||||||
|
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
||||||
|
|
||||||
|
- p_udp_hdr->uh_sum = udp_checksum;
|
||||||
|
- }
|
||||||
|
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
||||||
|
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
||||||
|
|
||||||
|
- /* restore IP header */
|
||||||
|
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
+ /* add 4 TCP pseudoheader fields */
|
||||||
|
+ /* copy IP source and destination fields */
|
||||||
|
+ memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
||||||
|
+
|
||||||
|
+ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
+ {
|
||||||
|
+ DPRINTF("+++ C+ mode calculating TCP checksum for "
|
||||||
|
+ "packet with %d bytes data\n", ip_data_len);
|
||||||
|
+
|
||||||
|
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_tcpip_hdr->zeros = 0;
|
||||||
|
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
||||||
|
+ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+
|
||||||
|
+ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
||||||
|
+
|
||||||
|
+ p_tcp_hdr->th_sum = 0;
|
||||||
|
+
|
||||||
|
+ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
+ DPRINTF("+++ C+ mode TCP checksum %04x\n",
|
||||||
|
+ tcp_checksum);
|
||||||
|
+
|
||||||
|
+ p_tcp_hdr->th_sum = tcp_checksum;
|
||||||
|
+ }
|
||||||
|
+ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
||||||
|
+ {
|
||||||
|
+ DPRINTF("+++ C+ mode calculating UDP checksum for "
|
||||||
|
+ "packet with %d bytes data\n", ip_data_len);
|
||||||
|
+
|
||||||
|
+ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
||||||
|
+ p_udpip_hdr->zeros = 0;
|
||||||
|
+ p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
||||||
|
+ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
||||||
|
+
|
||||||
|
+ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
||||||
|
+
|
||||||
|
+ p_udp_hdr->uh_sum = 0;
|
||||||
|
+
|
||||||
|
+ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
||||||
|
+ DPRINTF("+++ C+ mode UDP checksum %04x\n",
|
||||||
|
+ udp_checksum);
|
||||||
|
+
|
||||||
|
+ p_udp_hdr->uh_sum = udp_checksum;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* restore IP header */
|
||||||
|
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
38
xsa140-qemuu-3.patch
Normal file
38
xsa140-qemuu-3.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 043d28507ef7c5fdc34866f5e3b27a72bd0cd072 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:00 +0100
|
||||||
|
Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header
|
||||||
|
|
||||||
|
Transmit offload features access Ethernet and IP headers the packet. If
|
||||||
|
the packet is too short we must not attempt to access header fields:
|
||||||
|
|
||||||
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
|
...
|
||||||
|
eth_payload_data = saved_buffer + ETH_HLEN;
|
||||||
|
...
|
||||||
|
ip = (ip_header*)eth_payload_data;
|
||||||
|
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2161,6 +2161,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
{
|
||||||
|
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
||||||
|
|
||||||
|
+ /* Large enough for Ethernet and IP headers? */
|
||||||
|
+ if (saved_size < ETH_HLEN + sizeof(ip_header)) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* ip packet header */
|
||||||
|
ip_header *ip = NULL;
|
||||||
|
int hlen = 0;
|
52
xsa140-qemuu-4.patch
Normal file
52
xsa140-qemuu-4.patch
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 5a75d242fe019d05b46ef9bc330a6892525c84a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:01 +0100
|
||||||
|
Subject: [PATCH 4/7] rtl8139: check IP Header Length field
|
||||||
|
|
||||||
|
The IP Header Length field was only checked in the IP checksum case, but
|
||||||
|
is used in other cases too.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 19 ++++++++-----------
|
||||||
|
1 file changed, 8 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2197,6 +2197,10 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
|
||||||
|
hlen = IP_HEADER_LENGTH(ip);
|
||||||
|
+ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
|
||||||
|
@@ -2204,17 +2208,10 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
{
|
||||||
|
DPRINTF("+++ C+ mode need IP checksum\n");
|
||||||
|
|
||||||
|
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
||||||
|
- /* bad packet header len */
|
||||||
|
- /* or packet too short */
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ip->ip_sum = 0;
|
||||||
|
- ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
|
- hlen, ip->ip_sum);
|
||||||
|
- }
|
||||||
|
+ ip->ip_sum = 0;
|
||||||
|
+ ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
|
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
|
+ hlen, ip->ip_sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
33
xsa140-qemuu-5.patch
Normal file
33
xsa140-qemuu-5.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 6c79ea275d72bc1fd88bdcf1e7d231b2c9c865de Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:02 +0100
|
||||||
|
Subject: [PATCH 5/7] rtl8139: check IP Total Length field
|
||||||
|
|
||||||
|
The IP Total Length field includes the IP header and data. Make sure it
|
||||||
|
is valid and does not exceed the Ethernet payload size.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2202,7 +2202,12 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_protocol = ip->ip_p;
|
||||||
|
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
||||||
|
+
|
||||||
|
+ ip_data_len = be16_to_cpu(ip->ip_len);
|
||||||
|
+ if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+ ip_data_len -= hlen;
|
||||||
|
|
||||||
|
if (txdw0 & CP_TX_IPCS)
|
||||||
|
{
|
34
xsa140-qemuu-6.patch
Normal file
34
xsa140-qemuu-6.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 30aa7be430e7c982e9163f3bcc745d3aa57b6aa4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:03 +0100
|
||||||
|
Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header
|
||||||
|
|
||||||
|
TCP Large Segment Offload accesses the TCP header in the packet. If the
|
||||||
|
packet is too short we must not attempt to access header fields:
|
||||||
|
|
||||||
|
tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
||||||
|
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2221,6 +2221,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
|
||||||
|
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
||||||
|
{
|
||||||
|
+ /* Large enough for the TCP header? */
|
||||||
|
+ if (ip_data_len < sizeof(tcp_header)) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
|
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
31
xsa140-qemuu-7.patch
Normal file
31
xsa140-qemuu-7.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
References: bsc#939712 XSA-140
|
||||||
|
|
||||||
|
From 9a084807bf6ca7c16d997a236d304111894a6539 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Wed, 15 Jul 2015 18:17:04 +0100
|
||||||
|
Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field
|
||||||
|
|
||||||
|
The TCP Data Offset field contains the length of the header. Make sure
|
||||||
|
it is valid and does not exceed the IP data length.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/net/rtl8139.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
Index: xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
===================================================================
|
||||||
|
--- xen-4.5.1-testing.orig/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
+++ xen-4.5.1-testing/tools/qemu-xen-dir-remote/hw/net/rtl8139.c
|
||||||
|
@@ -2250,6 +2250,11 @@ static int rtl8139_cplus_transmit_one(RT
|
||||||
|
|
||||||
|
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
||||||
|
|
||||||
|
+ /* Invalid TCP data offset? */
|
||||||
|
+ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
|
||||||
|
+ goto skip_offload;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
|
int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
|
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
Loading…
x
Reference in New Issue
Block a user