Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Nov 2006 21:03:06 +0300
From:      Yar Tikhiy <yar@comp.chem.msu.su>
To:        freebsd-net@freebsd.org
Subject:   m_copy & if_simloop
Message-ID:  <20061126180306.GA64912@comp.chem.msu.su>

next in thread | raw e-mail | index | archive | help
Hi folks,

A friend user reported to me that rwhod wouldn't work in CURRENT
due to broken outgoing packets.  Here's an example:

16:15:28.212810 IP truncated-ip - 6865 bytes missing! (tos 0x0, ttl  64, id 28554, offset 0, flags [none], proto: UDP (17), length: 7169, bad cksum 11c (->c64b)!) 10.10.10.4.513 > 10.10.10.255.513: UDP, length 276
        0x0000:  4500 1c01 6f8a 0000 4011 011c 0a0a 0a04  E...o...@.......
                      ^^^^                ^^^^ broken fields
        0x0010:  0a0a 0aff 0201 0201 011c 0000 0101 0000  ................
        0x0020:  4565 9ef0 0000 0000 6467 0000 0000 0000  Ee......dg......
        0x0030:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0040:  0000 0000 0000 0000 0000 001a 0000 000e  ................
        0x0050:  0000 0005 4564 a5e7 7474 7976 3000 0000  ....Ed..ttyv0...
        0x0060:  726f 6f74 0000 0000 4565 9d4a 0000 01a6  root....Ee.J....
        0x0070:  7474 7976 3100 0000 726f 6f74 0000 0000  ttyv1...root....
        0x0080:  4565 9d4d 0000 000c 7474 7976 3200 0000  Ee.M....ttyv2...
        0x0090:  726f 6f74 0000 0000 4565 9d4f 0000 0099  root....Ee.O....
        0x00a0:  7474 7976 3300 0000 726f 6f74 0000 0000  ttyv3...root....
        0x00b0:  4565 9d52 0000 019e 7474 7976 3400 0000  Ee.R....ttyv4...
        0x00c0:  726f 6f74 0000 0000 4565 9d54 0000 019c  root....Ee.T....
        0x00d0:  7474 7976 3500 0000 726f 6f74 0000 0000  ttyv5...root....
        0x00e0:  4565 9d59 0000 0198 7474 7976 3600 0000  Ee.Y....ttyv6...
        0x00f0:  726f 6f74 0000 0000 4565 9d5b 0000 0195  root....Ee.[....
        0x0100:  7474 7976 3700 0000 726f 6f74 0000 0000  ttyv7...root....
        0x0110:  4565 9d5e 0000 0000 7474 7970 3100 0000  Ee.^....ttyp1...
        0x0120:  7961 7200 0000 0000 4565 8361 0000 04b2  yar.....Ee.a....

BTW, the problem manifests itself only if the packet is longer than
256 bytes.

The problem seems to stem from the following.  In ether_output(),
the broadcast packet is copied and looped back up the stack, now
via if_simloop().  The copy has been made with m_copy() since 4.4BSD.
I can't tell about the old days, but today m_copy() alias m_copym()
will copy mbufs but not mbuf clusters, which results in an effectively
read-only copy.  Such a copy must not be passed up the stack because
the stack is free to change it and thus destroy the original.  For
a long time, enough leading bytes were in plain mbuf(s) for the bug
to stay unnoticed.  However, the pattern changed in CURRENT some
day and -- here we are.

The problem can be cured by using m_dup() in place of m_copy()
(verified).

Is my analysis correct?

If so, here's an idea of a general fix.  Several source files do
the following:

	struct mbuf *mcopy = m_copy(m, 0, M_COPYALL);
	/* some even don't check mcopy for NULL here! */
	if_simloop(ifp, mcopy, family, hdrlen);

It's common code, so just a flag to if_simloop() cound be introduced
meaning "m_dup() the packet properly".  E.g.:

	if_simloop(ifp, m, family, hdrlen, M_DUP);

In STABLE, M_COPYALL can be added to hdrlen instead to preserve the
ABI.  M_COPYALL is defined as 1000000000 now, which allows for the
trick.

Comments?  Thanks!

Yar



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