Re: [PATCH net 1/1] net: gso: limit recursive IP-in-IP segmentation
From: David Laight
Date: Mon Sep 14 2026 - 04:10:08 EST
On Sun, 13 Sep 2026 18:46:53 -0400
Willem de Bruijn <willemdebruijn.kernel@xxxxxxxxx> wrote:
> Zihan Xi wrote:
> > IPIP GSO/TSO support makes IP-in-IP GSO dispatch re-enter
> > inet_gso_segment() or ipv6_gso_segment() for every nested IP header. The
> > only state that tracks this nesting is encap_level, which records header
> > bytes and has no recursion bound. A sufficiently deep chain can consume the
> > kernel stack before a transport GSO callback is reached.
> >
> > The unbounded callback nesting was introduced when inet_gso_segment() was
> > made stackable by "ipv4: gso: make inet_gso_segment() stackable". GRE GSO
> > support predated that change, and IP-in-IP GSO/TSO support later made the
> > affected path reachable.
> >
> > Track the number of IP GSO callbacks in skb_gso_cb and reject the 15th
> > callback entry. Thus 14 callback entries are allowed to complete;
> > GSO_RECURSION_LIMIT is the rejection threshold, not the number of
> > successful callbacks. Initialize the counter for each top-level GSO
> > operation and check it in both IPv4 and IPv6 handlers so mixed IP-in-IP
> > nesting is bounded.
> >
> > Fixes: 3347c9602955 ("ipv4: gso: make inet_gso_segment() stackable")
> > Cc: stable@xxxxxxxxxxxxxxx
> > Reported-by: Vega <vega@xxxxxxxxxx>
> > Assisted-by: LLM
> > Co-developed-by: Luxing Yin <root@xxxxxxxxxx>
> > Signed-off-by: Luxing Yin <root@xxxxxxxxxx>
> > Signed-off-by: Zihan Xi <zihanx@xxxxxxxxxx>
> > ---
> > include/net/gso.h | 9 +++++++++
> > net/core/gso.c | 1 +
> > net/ipv4/af_inet.c | 3 +++
> > net/ipv6/ip6_offload.c | 3 +++
> > 4 files changed, 16 insertions(+)
> >
> > diff --git a/include/net/gso.h b/include/net/gso.h
> > index 29975440cad5..2665acbb9205 100644
> > --- a/include/net/gso.h
> > +++ b/include/net/gso.h
> > @@ -19,10 +19,19 @@ struct skb_gso_cb {
> > int encap_level;
> > __wsum csum;
> > __u16 csum_start;
> > + /* Number of GSO callbacks this packet already went through. */
> > + u8 recursion_counter;
> > };
> > #define SKB_GSO_CB_OFFSET 32
> > #define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_GSO_CB_OFFSET))
> >
> > +#define GSO_RECURSION_LIMIT 15 /* First callback depth to reject. */
> > +static inline int gso_recursion_inc_test(struct sk_buff *skb)
>
> What is 15 based on? Is that where in your test stack overflow occurs?
>
> A realistic practical limit would likely already be smaller.
>
What is the recursion limit on sparc64?
(The minimum stack frame is 176 bytes.)
It would be more sensible to check the 'amount of stack remaining' than
the number of levels of recursion.
Even though that is still asking 'how long is a piece of string'.
David