Patchwork e1000: Fix TCP checksum overflow with TSO

login
register
mail settings
Submitter Alex Williamson
Date Nov. 5, 2010, 8:52 p.m.
Message ID <20101105205148.8161.25164.stgit@s20.home>
Download mbox | patch
Permalink /patch/70294/
State New
Headers show

Comments

Alex Williamson - Nov. 5, 2010, 8:52 p.m.
When adding the length to the pseudo header, we're not properly
accounting for overflow.

From: Mark Wu <dwu@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/e1000.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
Michael S. Tsirkin - Nov. 8, 2010, 10:51 a.m.
On Fri, Nov 05, 2010 at 02:52:08PM -0600, Alex Williamson wrote:
> When adding the length to the pseudo header, we're not properly
> accounting for overflow.
> 
> From: Mark Wu <dwu@redhat.com>
> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

Thanks, applied.

> ---
> 
>  hw/e1000.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/e1000.c b/hw/e1000.c
> index 532efdc..677165f 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -384,9 +384,12 @@ xmit_seg(E1000State *s)
>          } else	// UDP
>              cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
>          if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
> +            unsigned int phsum;
>              // add pseudo-header length before checksum calculation
>              sp = (uint16_t *)(tp->data + tp->tucso);
> -            cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
> +            phsum = be16_to_cpup(sp) + len;
> +            phsum = (phsum >> 16) + (phsum & 0xffff);
> +            cpu_to_be16wu(sp, phsum);
>          }
>          tp->tso_frames++;
>      }

Patch

diff --git a/hw/e1000.c b/hw/e1000.c
index 532efdc..677165f 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -384,9 +384,12 @@  xmit_seg(E1000State *s)
         } else	// UDP
             cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
         if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
+            unsigned int phsum;
             // add pseudo-header length before checksum calculation
             sp = (uint16_t *)(tp->data + tp->tucso);
-            cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
+            phsum = be16_to_cpup(sp) + len;
+            phsum = (phsum >> 16) + (phsum & 0xffff);
+            cpu_to_be16wu(sp, phsum);
         }
         tp->tso_frames++;
     }