Le jeu. 22 oct. 2026 à 14:43, Ilya Maximets <[email protected]> a écrit :
>
> On 10/22/26 11:22 AM, Jamal Hadi Salim wrote:
> > The issue:
> > pop_nsh() restores MAC_PROTO_ETHERNET when the popped NSH next-protocol
> > is TUN_P_ETHERNET, but nsh_pop() only guarantees that the NSH header is
> > in the linear area.  When the inner Ethernet header sits in a page
> > fragment, the datapath then claims an Ethernet header it cannot access
> > linearly.
> >
> > Output to an OVS internal vport then calls eth_type_trans(), which
> > pulls ETH_HLEN from an empty linear area and triggers the BUG in
> > __skb_pull():
> >
> >   kernel BUG at ./include/linux/skbuff.h:2830!
> >   RIP: 0010:eth_type_trans+0x335/0x500
> >   internal_dev_recv
> >   ovs_vport_send
> >   do_output
> >   do_execute_actions
> >   ovs_execute_actions
> >   ovs_dp_process_packet
> >   ovs_vport_receive
> >   internal_dev_xmit
> >
> > Conditions to recreate the bug:
> > On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
> > enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
> > internal port up with MTU 9000.  Install a flow matching an Ethernet/NSH
> > packet with a 24-byte MD1 header whose next-protocol is TUN_P_ETHERNET,
> > and actions pop_eth, pop_nsh, output to the local port.  With
> > CAP_NET_RAW, send a 4148-byte AF_PACKET/SOCK_RAW frame containing outer
> > Ethernet, the NSH header, inner Ethernet and 4096 payload bytes.  The
> > two pops consume the linear headers and expose the inner Ethernet header
> > in page fragments.
> >
> > The fix:
> > Pull the inner Ethernet header into the linear area before restoring
> > MAC_PROTO_ETHERNET.  This is the NSH counterpart of the MPLS/TEB
> > producer fix in the previous patch.
> >
> > Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
> > Link: 
> > https://lore.kernel.org/netdev/[email protected]/
> > Cc: [email protected]
> > Signed-off-by: Jamal Hadi Salim <[email protected]>
> > ---
> >  net/openvswitch/actions.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> > index 03b31e33e880..cb7e16c6a8ef 100644
> > --- a/net/openvswitch/actions.c
> > +++ b/net/openvswitch/actions.c
> > @@ -314,10 +314,13 @@ static int pop_nsh(struct sk_buff *skb, struct 
> > sw_flow_key *key)
> >               return err;
> >
> >       /* safe right before invalidate_flow_key */
> > -     if (skb->protocol == htons(ETH_P_TEB))
> > +     if (skb->protocol == htons(ETH_P_TEB)) {
> > +             if (!pskb_may_pull(skb, ETH_HLEN))
> > +                     return -ENOMEM;
> >               key->mac_proto = MAC_PROTO_ETHERNET;
> > -     else
> > +     } else {
> >               key->mac_proto = MAC_PROTO_NONE;
> > +     }
> >       invalidate_flow_key(key);
> >       return 0;
> >  }
>
> Reviewed-by: Ilya Maximets <[email protected]>

Reviewed-by: Eric Dumazet <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to