Netdev List
 help / color / mirror / Atom feed
From: Ido Schimmel <idosch@nvidia.com>
To: Qi Tang <tpluszz77@gmail.com>
Cc: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com,
	edumazet@google.com, netdev@vger.kernel.org, fw@strlen.de,
	lyutoon@gmail.com, stable@vger.kernel.org,
	David Ahern <dsahern@kernel.org>, Simon Horman <horms@kernel.org>
Subject: Re: [PATCH net v2 1/4] ipv4: validate ip_options length in __ip_options_echo() against skb tail
Date: Mon, 25 May 2026 17:47:07 +0300	[thread overview]
Message-ID: <20260525144707.GA217485@shredder> (raw)
In-Reply-To: <20260524041442.2432071-2-tpluszz77@gmail.com>

On Sun, May 24, 2026 at 12:14:35PM +0800, Qi Tang wrote:
> __ip_options_echo() re-reads each option length byte (RR/TS/SRR/CIPSO)
> from skb->data when building the echoed options into a 40-byte
> __data[] buffer.  __ip_options_compile() saved only the option offset
> into IPCB(skb)->opt, not the length.  An nftables LOCAL_IN payload
> write reachable from an unprivileged user namespace can mutate the
> length byte between parse and recvmsg, turning a parse-time validated
> 7-byte option into a 255-byte read.
> 
>   unsigned char optbuf[sizeof(struct ip_options) + 40];
>   /* in __ip_options_echo: */
>   optlen = sptr[sopt->rr + 1];        /* re-read; nft can mutate */
>   memcpy(dptr, sptr + sopt->rr, optlen); /* into 40-byte buffer */
> 
> The destination is a stack buffer in ip_cmsg_recv_retopts() and a
> DEFINE_RAW_FLEX() buffer in icmp.c / ip_output.c sized
> IP_OPTIONS_DATA_FIXED_SIZE (40).  KASAN reports a stack-out-of-bounds
> write of size 255:
> 
>   BUG: KASAN: stack-out-of-bounds in __ip_options_echo+0x7fc/0x1310
>   Write of size 255 at addr ffff88800a657950
>    __asan_memcpy+0x3c/0x60
>    __ip_options_echo+0x7fc/0x1310
>    ip_cmsg_recv_offset+0x58b/0xd10
>    udp_recvmsg+0x8da/0xc20
>    ____sys_recvmsg+0x1b1/0x620
> 
> Validate that each re-read option length stays within
> skb_tail_pointer(skb) before the memcpy.
> 
> Cc: stable@vger.kernel.org
> Reported-by: Qi Tang <tpluszz77@gmail.com>
> Reported-by: Tong Liu <lyutoon@gmail.com>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Qi Tang <tpluszz77@gmail.com>
> ---
>  net/ipv4/ip_options.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
> index be8815ce3ac24..1cc6096e6dd9d 100644
> --- a/net/ipv4/ip_options.c
> +++ b/net/ipv4/ip_options.c
> @@ -91,6 +91,8 @@ int __ip_options_echo(struct net *net, struct ip_options *dopt,
>  
>  	if (sopt->rr) {
>  		optlen  = sptr[sopt->rr+1];
> +		if (sptr + sopt->rr + optlen > skb_tail_pointer(skb))
> +			return -EINVAL;

Both Sashiko instances flag valid issues. Please go over them. The most
obvious issues are:

1. This check only avoids reading past the skb's linear buffer. The
memcpy() below can still overflow the destination buffer which is only
40 bytes.

2. There is no validation against the original IP options length
(sopt->optlen), so we might be echoing bytes from the skb payload (past
the IP options).

>  		soffset = sptr[sopt->rr+2];
>  		dopt->rr = dopt->optlen + sizeof(struct iphdr);
>  		memcpy(dptr, sptr+sopt->rr, optlen);
> @@ -105,6 +107,8 @@ int __ip_options_echo(struct net *net, struct ip_options *dopt,
>  	}
>  	if (sopt->ts) {
>  		optlen = sptr[sopt->ts+1];
> +		if (sptr + sopt->ts + optlen > skb_tail_pointer(skb))
> +			return -EINVAL;
>  		soffset = sptr[sopt->ts+2];
>  		dopt->ts = dopt->optlen + sizeof(struct iphdr);
>  		memcpy(dptr, sptr+sopt->ts, optlen);
> @@ -145,6 +149,8 @@ int __ip_options_echo(struct net *net, struct ip_options *dopt,
>  		__be32 faddr;
>  
>  		optlen  = start[1];
> +		if (start + optlen > skb_tail_pointer(skb))
> +			return -EINVAL;
>  		soffset = start[2];
>  		doffset = 0;
>  		if (soffset > optlen)
> @@ -174,6 +180,8 @@ int __ip_options_echo(struct net *net, struct ip_options *dopt,
>  	}
>  	if (sopt->cipso) {
>  		optlen  = sptr[sopt->cipso+1];
> +		if (sptr + sopt->cipso + optlen > skb_tail_pointer(skb))
> +			return -EINVAL;
>  		dopt->cipso = dopt->optlen+sizeof(struct iphdr);
>  		memcpy(dptr, sptr+sopt->cipso, optlen);
>  		dptr += optlen;
> -- 
> 2.47.3
> 

  reply	other threads:[~2026-05-25 14:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-24  4:14 [PATCH net v2 0/4] net: trust-after-modification fixes for IPv4 options + netlabel Qi Tang
2026-05-24  4:14 ` [PATCH net v2 1/4] ipv4: validate ip_options length in __ip_options_echo() against skb tail Qi Tang
2026-05-25 14:47   ` Ido Schimmel [this message]
2026-05-24  4:14 ` [PATCH net v2 2/4] ipv4: ipmr: clamp ip_hdrlen against skb_headlen in ipmr_cache_report Qi Tang
2026-05-24  4:14 ` [PATCH net v2 3/4] netlabel: validate CALIPSO option against skb tail in netlbl_skbuff_getattr Qi Tang
2026-05-24  4:14 ` [PATCH net v2 4/4] netlabel: validate CIPSO " Qi Tang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260525144707.GA217485@shredder \
    --to=idosch@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=lyutoon@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=tpluszz77@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox