Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Jul 2010 06:48:58 GMT
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/148307: Incorrect alignment checks in sys/mips/atheros/if_arge.c
Message-ID:  <201007020648.o626mwMb062571@ref8-amd64.freebsd.org>
Resent-Message-ID: <201007020650.o626o1hr008882@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         148307
>Category:       kern
>Synopsis:       Incorrect alignment checks in sys/mips/atheros/if_arge.c
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 02 06:50:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Adrian Chadd
>Release:        FreeBSD 9.0-CURRENT mips
>Organization:
>Environment:

FreeBSD 9.0-CURRENT, from ~ january (verified the arge driver hasn't
changed since.)

Hardware: Ubiquiti Routerstation Pro, AR71XX series SoC.
Atheros wireless NIC(s)in HostAP mode. (AR5212/AR9160.)

>Description:

2 bytes would appear in between the ethernet header and the
ethernet payload in some circumstances. In this particular
circumstance, it's when bridging over GRE tunnels. Traffic
from an ethernet connected host worked, but traffic from
a wireless connected host didn't.

The if_arge() TX code would check the first fragment to see
whether it's aligned and if not, a call to m_defrag() would
align and pack the fragments.

The hardware requires all fragments to be 4 bytes aligned -
and that all fragments save the last be a size that's
a multiple of 4 bytes.

In the case I was seeing, an encapsulated packet would be
an mbuf chain consisting of two parts. The first mbuf would
have a 14 byte ethernet header (6 byte src, 6 byte dst, 2 byte
ethertype) and then the original payload in the second mbuf.
This didn't trigger the call to m_defrag() and thus the
packet was passed along, untouched.

"Normal" traffic almost exclusively was misaligned and called
m_defrag().

>How-To-Repeat:

Implement a pair of units which are bridging over GRE/IP:

* create bridge0
* create gre0, mtu 1500, setup IPs as needed
* throw arge1, wlan0, etc into bridge0
* throw gre0 into bridge0
* send traffic from wlan0 to a host on the other side of the
  bridge - this fails

>Fix:

The fix would be to check each mbuf in the TX chain for size
and alignment then call m_defrag() if the constraints are
missed.

My local fix was just to always call m_defrag() for now.
It is inefficient but it resolves the issue.
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007020648.o626mwMb062571>