Re: [PATCH net v3] ipv6: seg6: clear IPv4 control block on IPIP decapsulation

Andrea Mayer <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <[email protected]>
On Mon, 10 Aug 2026 15:47:31 +0000
David Lee <[email protected]> wrote:

Thanks Kyle and David for the v3. The code looks good. What follows is
about the commit message.

I think the commit message is missing some information that the review
needs now, and that anyone reading git log will need later, since this
patch is Cc: stable.

> From: Kyle Zeng <[email protected]>
> 
> End.DX4 and End.DT4 decapsulate an IPv4 packet through
> decap_and_validate() and send it directly to IPv4 routing. The inner
> packet therefore bypasses ip_rcv_core(), which normally clears IPCB
> before IPv4 interprets skb->cb.
> 
> The skb instead retains IP6CB data from the outer packet. IPv6
> extension-header offsets overlap IPv4 option fields, so IPv4 can treat
> those offsets as saved option metadata. __ip_options_echo() can then
> copy beyond the allocation for saved options.
> 

This says the offsets overlap, but not which stale field has to be
non-zero for the copy to be attempted. IPCB->opt.optlen shares a byte
with IP6CB->lastopt, and __ip_options_echo() returns before any copy
when the optlen it is given is zero. What the outer packet has to look
like for that byte to be non-zero, and whether the sender controls it,
are not stated.

> Separate End.DX4 and End.DT4 reproducers on the unpatched v7.2-rc5
> kernel both produced:
> 
>   BUG: KASAN: slab-out-of-bounds in __ip_options_echo()
>   Write of size 255
> 
> The End.DX4 trace passes through input_action_end_dx4_finish() and
> input_action_end_dx4(), while the End.DT4 trace passes through
> input_action_end_dt4().
> 

Pasting the call stack would show how __ip_options_echo() is reached.

> When decap_and_validate() handles IPPROTO_IPIP, save the ingress
> interface from IP6CB, clear IPCB, and restore the saved value. Doing
> this in the common decapsulation path covers End.DX4, End.DT4, and
> End.DT46's IPv4 arm.
> 
> Use IP6CB(skb)->iif rather than skb->skb_iif. These actions run after
> l3mdev processing, which can replace skb_iif with the L3 master;
> IP6CB iif still records the receiving interface set at IPv6 ingress.
> 
> Fixes: 891ef8dd2a8d ("ipv6: sr: implement additional seg6local actions")
> Cc: [email protected]
> Suggested-by: Andrea Mayer <[email protected]>
> Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
> Signed-off-by: Kyle Zeng <[email protected]>
> Co-developed-by: David Lee <[email protected]>
> Signed-off-by: David Lee <[email protected]>
> ---
> Changes in v3:
> - Clear IPCB in the common IPPROTO_IPIP decapsulation path so End.DX4,
>   End.DT4, and End.DT46's IPv4 arm are covered.
> - Preserve the ingress interface from IP6CB instead of skb->skb_iif,
>   which can identify the VRF master after l3mdev processing.
> - Update the Fixes tag to the commit that introduced End.DX4.
> - Include the End.DX4 and End.DT4 KASAN evidence.
> 
> v2: https://lore.kernel.org/netdev/[email protected]/
> v1: https://lore.kernel.org/all/[email protected]/ 
> 
>  net/ipv6/seg6_local.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
> index 2b41e4c0dddd..95ea0b62729a 100644
> --- a/net/ipv6/seg6_local.c
> +++ b/net/ipv6/seg6_local.c
> @@ -256,6 +256,13 @@ static bool decap_and_validate(struct sk_buff *skb, int proto)
>  	if (iptunnel_pull_offloads(skb))
>  		return false;
>  
> +	if (proto == IPPROTO_IPIP) {
> +		int iif = IP6CB(skb)->iif;
> +
> +		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
> +		IPCB(skb)->iif = iif;
> +	}
> +
>  	return true;
>  }
>  

IMHO, the commit message is worth a new revision.

Thanks,

Ciao,
Andrea
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.