>Synopsis:      vxlan(4) unaligned traps crashes on alpha
>Category:      alpha
>Environment:
        System      : OpenBSD 6.0

        Details     : OpenBSD 6.0 (GENERIC) #469: Wed Jul 27 03:13:14 MDT
2016
             [email protected]:/usr/src/sys/arch/alpha/compile/G
ENERIC

        Architecture: OpenBSD.alpha
        Machine     : alpha
>Description:

        Creating a vxlan(4) instance and setting an IPv6 address on it will
        cause an unaligned access fault on alpha, tested on my DS10 and
        DS15 systems. In OpenBSD 5.9, the crash happened only after e.g. a
        ping6(8) like ff02::1%vxlan0...

fatal kernel trap:

    trap entry = 0x4 (unaligned access fault)
    a0         = 0xfffffc0037333e7e
    a1         = 0x28
    a2         = 0x2
    pc         = 0xfffffc00007efb70
    ra         = 0xfffffc00007efb14
    curproc    = 0xfffffc003fc70268
        pid = 8962, comm = ifconfig

panic: trap
Stopped at      Debugger+0x8:   lda     sp,10(sp)
   TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
* 8962   8962      0         0x3          0    0  ifconfig
Debugger(4, fffffc0000ced0d0, fffffd01fc0003fd, 8, 3, fffffc0000000008) at
Debugger+0x8
panic(?, 28, 2, 4, fffffe0014cdf670, 8) at panic+0xcc
trap(?, ?, ?, ?, ?, 8) at trap+0x138
XentUna(?, ?, ?, ?, ?, 8) at XentUna+0x20
vxlan_output(?, 24, 2, fffffe0014cdfaa8, fffffe0014cdf8c8, 18) at
vxlan_output+0xa0
vxlanstart(?, ?, 2, fffffe0014cdfaa8, fffffe0014cdf8c8, 18) at
vxlanstart+0x64
ifq_dequeue(?, ?, 2, fffffe0014cdfaa8, fffffe0014cdf8c8, 18) at
ifq_dequeue+0x34
http://www.openbsd.org/ddb.html describes the minimum info required in bug
reports.  Insufficient info makes it difficult to find and fix bugs.
ddb>

        Once this was fixed, the machine crashes at an incoming packet on
        the vxlan(4) interface.

fatal kernel trap:

    trap entry = 0x4 (unaligned access fault)
    a0         = 0xfffffc0001c63072
    a1         = 0x28
    a2         = 0x6
    pc         = 0xfffffc00007b6ab8
    ra         = 0xfffffc00007b68fc
    curproc    = 0xfffffc003fd5a960
        pid = 82287, comm = softnet

panic: trap
Stopped at      Debugger+0x8:   lda     sp,10(sp)
   TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
*82287  82287      0     0x14000      0x210    0  softnet
Debugger(1, fffffd01fc0003f8, fffffd01fc0003fd, 8, 3, fffffd0100000008) at
Debugger+0x8
panic(?, 28, 6, 4, fffffe0014d83c20, fffffc0000000008) at panic+0xcc
trap(?, ?, ?, ?, ?, fffffc0000000008) at trap+0x138
XentUna(?, ?, ?, ?, ?, fffffc0000000008) at XentUna+0x20
ip6_input(fffffc003ff85f00, d3f2152afb6f8db3, fffffc0000906360, 0, 0,
fffffc0037296e00) at ip6_input+0x208
ip6intr(fffffc003ff85f00, d3f2152afb6f8db3, fffffc0000906360, 0, 0,
fffffc0037296e00) at ip6intr+0x24
http://www.openbsd.org/ddb.html describes the minimum info required in bug
reports.  Insufficient info makes it difficult to find and fix bugs.
ddb>

>How-To-Repeat:
        For the first kernel trap:
        # ifconfig vxlan0 create
        # ifconfig vxlan0 inet6 2001:db8::1/32

        Then, ping that address from the remote to cause another kernel
trap:
        # ping6 2001:db8::1

>Fix:
I haven't fully understood how mbuf's work but by adding a m_pullup(9) after
M_PREPEND() seems to atleast make the first panic go away.

How many bytes for m_pullup? In vxlan_output, sizeof (*vi) work but should
we do more?

In vxlan_lookup, m_pullup by sizeof (*eh) was the only thing i could think
of trying.

I remember that back in 2002 (kernel/3037 by mickey@) we had similar
unaligned access issues with rl(4). How times go by...

TIA,
Dennis.

--- sys/net/if_vxlan.c.orig     Thu Oct  6 10:15:03 2016
+++ sys/net/if_vxlan.c  Thu Oct 13 17:24:17 2016
@@ -551,6 +551,11 @@
        m_adj(m, skip);
        ifp = &sc->sc_ac.ac_if;

+       m = m_pullup(m, sizeof(*eh));
+       if (m == NULL) {
+               ifp->if_ierrors++;
+               return (ENOBUFS);
+       }
        if ((eh = mtod(m, struct ether_header *)) == NULL)
                return (EINVAL);

@@ -594,6 +599,12 @@

        /* VXLAN header */
        M_PREPEND(m, sizeof(*vi), M_DONTWAIT);
+       if (m == NULL) {
+               ifp->if_oerrors++;
+               return (ENOBUFS);
+       }
+
+       m = m_pullup(m, sizeof(*vi));
        if (m == NULL) {
                ifp->if_oerrors++;
                return (ENOBUFS);

Reply via email to