Thread (4 messages) flat view 4 messages, 1 author, 5d ago

[RFC net-next v2 0/3] bonding: fix NS probe transmit over stacked VLANs

From: Xiang Mei (Microsoft) <hidden>
Date: 2026-07-29 23:01:30
Also in: lkml

The bonding NS monitor (ns_ip6_target) builds a Neighbour
Solicitation with ndisc_ns_create() and tags it for the slave's VLAN path in
bond_ns_send().  ndisc_ns_create() returns only the ICMPv6 message: the IPv6
and link-layer headers are pushed later, by ndisc_send_skb().  bond_ns_send()
however hands that bare skb to bond_handle_vlan() first, which is too early:

  - bond_handle_vlan() inserts each inner tag with mac_len = ETH_HLEN, so it
    writes 12 bytes into the ICMPv6 message (inside the target address) when no
    Ethernet header is present yet.  Any config with two or more stacked VLAN
    devices therefore emits a probe no peer can answer.

  - Each inner tag also eats VLAN_HLEN of the headroom that was reserved for
    the IPv6 header.  With LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) = 56
    bytes, six stacked VLAN devices leave 36 and the subsequent
    ip6_nd_hdr() -> skb_push(sizeof(struct ipv6hdr)) underflows past skb->head:

    skbuff: skb_under_panic: text:ffffffff85eef44b len:84 put:40
      head:ffff88801400b740 data:ffff88801400b73c
      tail:0x50 end:0x180 dev:veth0
    kernel BUG at net/core/skbuff.c:214!
    Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
    Workqueue: bond0 bond_arp_monitor
    RIP: 0010:skb_panic+0x142/0x230
    Call Trace:
     skb_push (net/core/skbuff.c:224)
     ndisc_send_skb (net/ipv6/ndisc.c:454 net/ipv6/ndisc.c:506)
     bond_ns_send (drivers/net/bonding/bond_main.c:3255)
     bond_ns_send_all (drivers/net/bonding/bond_main.c:3313)
     bond_arp_monitor (drivers/net/bonding/bond_main.c:3458)
     process_one_work (kernel/workqueue.c:3322)
     worker_thread (kernel/workqueue.c:3405)
     kthread (kernel/kthread.c:436)
    Kernel panic - not syncing: Fatal exception

The minimal fix for just the panic is a skb_cow_head() before ndisc_send_skb();
it stops the crash but leaves the packet malformed for two or more stacked
VLANs, because the tags are still inserted into a header-less skb.  This series
instead fixes the root cause: it builds the probe in the same order the rest of
the stack uses, which removes the corruption and the headroom underflow at once.

Approach
========
  1/3  Export the ndisc route attach as ndisc_attach_dst().  ndisc_send_skb()
       both attaches a route and transmits; a caller that has to build the
       link-layer header itself needs only the attach, because
       ip6_route_me_harder() in the LOCAL_OUT path dereferences skb_dst()
       unconditionally and icmp6_dst_alloc()/icmpv6_flow_init() are not
       exported.  No behavioural change for existing callers.

  2/3  Rework bond_ns_send() to build headers in stack order:
         - bond_ns_build_ip6hdr() pushes the IPv6 header and computes the checksum;
         - the probe then traverses NF_INET_LOCAL_OUT as a bare L3 packet, so
           netfilter sees skb->data at the IPv6 header rather than at a
           half-built Ethernet frame;
         - only once the hooks accept it does bond_ns_add_llhdr() push the
           link-layer header and bond_handle_vlan() add the VLAN tags, after
           which the probe is transmitted on the slave being tested.
       With the headers pushed first, skb_vlan_push() grows the headroom
       itself, so no skb_cow_head() is needed.

  3/3  Convert bond_handle_vlan() to skb_vlan_push(), which inserts the tags at
       the correct offset once the Ethernet header exists, and share the path
       with the ARP probe.

Why RFC
=======
I understand the security issues, but I am not familiar with the related
development concerns.  I have tried my best to learn and follow similar
implementations, but still not sure if it's complete/missing any problems.

Testing
=======
Reproduced the skb_under_panic and the malformed probe on a bond over 6 stacked
VLAN devices, and verified correct NS probes (accepted by the peer, correct
checksum and tag stack) with 0, 1, 2, 5 and 6 stacked VLAN devices after the
series.

Xiang Mei (Microsoft) (3):
  ipv6: ndisc: export the route attach as ndisc_attach_dst()
  bonding: build NS probe headers before inserting VLAN tags
  bonding: use skb_vlan_push() for probe tags

 drivers/net/bonding/bond_main.c | 144 ++++++++++++++++++++++++++------
 include/net/ndisc.h             |   3 +
 net/ipv6/ndisc.c                |  53 ++++++++----
 3 files changed, 160 insertions(+), 40 deletions(-)

-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help