All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
Cc: linux-security-module@vger.kernel.org
Subject: Re: [PATCH net v2 1/2] ipv4: recompile IP options on a private copy in ipv4_send_dest_unreach()
Date: Tue, 10 Nov 2026 13:17:47 +0000	[thread overview]
Message-ID: <sashiko-outbox-207109@kernel.org> (raw)
In-Reply-To: <20261109131736.3060756-2-edumazet@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] ipv4: skb->head reallocation and ihl TOCTOU in
  ipv4_send_dest_unreach()
- [High] ipv4: uninitialized headroom access after pskb_copy() when
  network_offset < 0
--

commit 5a814100bdfbbe07fb37410d0b393cb7deb2e38a
Author: Eric Dumazet <edumazet@kernel.org>

ipv4: recompile IP options on a private copy in ipv4_send_dest_unreach()

This commit uses pskb_copy() in ipv4_send_dest_unreach() so IP options are
recompiled and echoed on a private skb copy rather than modifying the
caller's skb.

> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 3a90c8d28b940..9af72cb892034 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -1256,6 +1256,7 @@ EXPORT_INDIRECT_CALLABLE(ipv4_dst_check);
>  
>  static void ipv4_send_dest_unreach(struct sk_buff *skb)
>  {
> +	struct sk_buff *nskb = NULL;
>  	struct inet_skb_parm parm;
>  	struct net_device *dev;
>  	int res;
> @@ -1271,6 +1272,16 @@ static void ipv4_send_dest_unreach(struct sk_buff *skb)
>  	if (ip_hdr(skb)->ihl > 5) {
>  		if (!pskb_network_may_pull(skb, ip_hdr(skb)->ihl * 4))
>  			return;
> +
> +		/* __ip_options_compile() writes into the options, and
> +		 * callers of dst_link_failure() may cache pointers into
> +		 * skb->head: work on a private copy.
> +		 */
> +		nskb = pskb_copy(skb, GFP_ATOMIC);
> +		if (!nskb)
> +			return;
> +		skb = nskb;

[Severity: High]
Can calling pskb_network_may_pull() on the caller's skb before pskb_copy()
still reallocate skb->head and cause a use-after-free in callers of
dst_link_failure()?

Tunnel transmit paths such as ipip_tunnel_xmit() and ipgre_xmit() call
pskb_inet_may_pull(), which only pulls sizeof(struct iphdr) and leaves IPv4
options in nonlinear fragments.  When ip_tunnel_xmit() calls
dst_link_failure(skb) before skb_cow_head(), pskb_network_may_pull(skb,
ip_hdr(skb)->ihl * 4) pulls the option bytes via __pskb_pull_tail() ->
pskb_expand_head() on the caller's skb (and pskb_copy() itself can call
skb_orphan_frags() -> skb_unclone() on a cloned skb with zerocopy frags),
freeing the old skb->head that ip_tunnel_xmit()'s cached inner_iph and
tnl_params pointers still reference.

> +
>  		parm.opt.optlen = ip_hdr(skb)->ihl * 4 - sizeof(struct iphdr);

[Severity: High]
Does re-reading ip_hdr(skb)->ihl after pskb_copy() also allow a TOCTOU race
when skb->head is shared, or an uninitialized read when
skb_network_offset(skb) is negative?

If a concurrent clone modifies ip_hdr(skb)->ihl between the check on the
original skb and pskb_copy(), re-reading ip_hdr(nskb)->ihl without
re-validating it can underflow parm.opt.optlen or exceed the pulled length
in nskb, leading to out-of-bounds accesses in __ip_options_compile() and
__ip_options_echo().

Separately, when a packet is redirected (for example via act_mirred or
bpf_redirect) to an NBMA GRE device with header_ops set, ipgre_xmit() pulls
pull_len bytes before gre_build_header() pushes tun_hlen, entering
ip_tunnel_xmit() -> dst_link_failure() with a negative
skb_network_offset(skb).  pskb_network_may_pull() accepts negative network
offsets, but pskb_copy() only copies data starting at skb->data and leaves
the headroom [nskb->head .. nskb->data] uninitialized while preserving
nskb->network_header in that headroom.  ip_hdr(nskb) then points into
uninitialized heap memory, corrupting parm.opt.optlen and causing
out-of-bounds reads and writes in __ip_options_compile().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261109131736.3060756-1-edumazet@kernel.org?part=1

  reply	other threads:[~2026-11-10 13:17 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 13:17 [PATCH net v2 0/2] ipv4: do not write shared IP options when sending ICMP errors Eric Dumazet
2026-11-09 13:17 ` [PATCH net v2 1/2] ipv4: recompile IP options on a private copy in ipv4_send_dest_unreach() Eric Dumazet
2026-11-10 13:17   ` sashiko-bot [this message]
2026-11-10 14:04   ` netdev-bot+sashiko
2026-11-12 13:46   ` Ido Schimmel
2026-11-12 14:28     ` Paolo Abeni
2026-11-09 13:17 ` [PATCH net v2 2/2] cipso: unshare headers before recompiling IP options in cipso_v4_error() Eric Dumazet
2026-11-09 21:43   ` Paul Moore
2026-11-10 13:17   ` sashiko-bot

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=sashiko-outbox-207109@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.