From: Hangbin Liu <hangbin.liu@linux.dev>
To: Andrea Mayer <andrea.mayer@uniroma2.it>
Cc: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
David Ahern <dsahern@kernel.org>, Simon Horman <horms@kernel.org>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
David Lebrun <david.lebrun@uclouvain.be>,
Stefano Salsano <stefano.salsano@uniroma2.it>
Subject: Re: [PATCH net] seg6: ensure packet data is writable before modifying SRH and IPv6 DA
Date: Tue, 29 Sep 2026 11:05:02 +0800 [thread overview]
Message-ID: <arsqomcYCLJqtWSC@fedora> (raw)
In-Reply-To: <20260925133807.32-1-andrea.mayer@uniroma2.it>
Hi Andrea,
On Fri, Sep 25, 2026 at 03:38:07PM +0200, Andrea Mayer wrote:
> advance_nextseg() modifies the SRH Segments Left field and the IPv6
> destination address without ensuring the packet data is writable.
> seg6_next_csid_advance_arg() has the same problem when it advances the
> NEXT-C-SID argument in the destination address.
>
> The skb may be cloned, for example by an AF_PACKET socket receiving on
> the ingress device. advance_nextseg() and seg6_next_csid_advance_arg()
> then write into the packet data shared with the clone. A read from that
> socket can return the modified packet instead of the received one. The
> simplified path below shows this for advance_nextseg():
>
> __netif_receive_skb_one_core
> __netif_receive_skb_core
> deliver_skb [orig: users=2, cloned=0]
> packet_rcv
> skb_clone clone queued to the AF_PACKET socket
> consume_skb(orig) [orig: users=1, cloned=1]
> ipv6_rcv
> ip6_rcv_core skb_share_check: no-op [orig: users=1]
> [...]
> input_action_end_core
> advance_nextseg writes into the data shared with the clone
>
> Call skb_ensure_writable() in advance_nextseg() and in
> seg6_next_csid_advance_arg() before they modify the packet data.
> skb_ensure_writable() may reallocate skb->head, which invalidates the
> pointers into the packet data taken before the call.
> advance_nextseg() now returns a valid SRH pointer, or NULL if
> skb_ensure_writable() fails.
> seg6_next_csid_advance_arg() takes the pointer to the destination
> address from the skb after skb_ensure_writable().
> On failure, the callers drop the packet with SKB_DROP_REASON_NOMEM.
>
> Fixes: 140f04c33bbc ("ipv6: sr: implement several seg6local actions")
> Fixes: 848f3c0d4769 ("seg6: add NEXT-C-SID support for SRv6 End behavior")
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> ---
> net/ipv6/seg6_local.c | 140 +++++++++++++++++++++++++++++++++++-------
> 1 file changed, 117 insertions(+), 23 deletions(-)
[...]
>
> static int input_action_end_finish(struct sk_buff *skb,
> @@ -408,31 +454,42 @@ static int input_action_end_finish(struct sk_buff *skb,
> static int input_action_end_core(struct sk_buff *skb,
> struct seg6_local_lwt *slwt)
> {
> + enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
> struct ipv6_sr_hdr *srh;
> + int err = -EINVAL;
>
> srh = get_and_validate_srh(skb);
> if (!srh)
> goto drop;
>
> - advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
> + srh = advance_nextseg(skb, srh, &reason);
> + if (!srh) {
> + err = -ENOMEM;
> + goto drop;
> + }
The srh is not used in the later function, maybe just
if (!advance_nextseg(skb, srh, &reason)) {
err = -ENOMEM;
goto drop;
}
>
> return input_action_end_finish(skb, slwt);
>
> drop:
> - kfree_skb(skb);
> - return -EINVAL;
> + kfree_skb_reason(skb, reason);
> + return err;
> }
>
> static int end_next_csid_core(struct sk_buff *skb, struct seg6_local_lwt *slwt)
> {
> const struct seg6_flavors_info *finfo = &slwt->flv_info;
> struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
> + enum skb_drop_reason reason;
>
> if (seg6_next_csid_is_arg_zero(daddr, finfo))
> return input_action_end_core(skb, slwt);
>
> /* update DA */
> - seg6_next_csid_advance_arg(daddr, finfo);
> + reason = seg6_next_csid_advance_arg(skb, finfo);
> + if (reason) {
> + kfree_skb_reason(skb, reason);
> + return -ENOMEM;
> + }
>
> return input_action_end_finish(skb, slwt);
> }
> @@ -448,19 +505,25 @@ static int input_action_end_x_finish(struct sk_buff *skb,
> static int input_action_end_x_core(struct sk_buff *skb,
> struct seg6_local_lwt *slwt)
> {
> + enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
> struct ipv6_sr_hdr *srh;
> + int err = -EINVAL;
>
> srh = get_and_validate_srh(skb);
> if (!srh)
> goto drop;
>
> - advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
> + srh = advance_nextseg(skb, srh, &reason);
> + if (!srh) {
> + err = -ENOMEM;
> + goto drop;
> + }
Same here and all later similar functions.
>
> return input_action_end_x_finish(skb, slwt);
>
> drop:
> - kfree_skb(skb);
> - return -EINVAL;
> + kfree_skb_reason(skb, reason);
> + return err;
> }
>
[...]
>
> @@ -1434,6 +1523,7 @@ static int input_action_end_bpf(struct sk_buff *skb,
> struct seg6_local_lwt *slwt)
> {
> struct seg6_bpf_srh_state *srh_state;
> + enum skb_drop_reason reason;
> struct ipv6_sr_hdr *srh;
> int ret;
>
> @@ -1442,7 +1532,11 @@ static int input_action_end_bpf(struct sk_buff *skb,
> kfree_skb(skb);
> return -EINVAL;
> }
> - advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
> + srh = advance_nextseg(skb, srh, &reason);
> + if (!srh) {
> + kfree_skb_reason(skb, reason);
> + return -ENOMEM;
> + }
The srh here is still needed by later srh_state->srh = srh; so we can keep it.
Thanks
Hangbin
next prev parent reply other threads:[~2026-09-29 3:05 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 13:38 [PATCH net] seg6: ensure packet data is writable before modifying SRH and IPv6 DA Andrea Mayer
2026-09-29 2:30 ` patchwork-bot+netdevbpf
2026-09-29 3:05 ` Hangbin Liu [this message]
2026-09-29 23:39 ` Andrea Mayer
2026-09-30 0:44 ` Hangbin Liu
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=arsqomcYCLJqtWSC@fedora \
--to=hangbin.liu@linux.dev \
--cc=andrea.mayer@uniroma2.it \
--cc=davem@davemloft.net \
--cc=david.lebrun@uclouvain.be \
--cc=dsahern@kernel.org \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stefano.salsano@uniroma2.it \
/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.